import base64
import random
from django.utils import timezone
import shutil
import asyncio
from  datetime import datetime, timedelta
import json
import time
import uuid
from django.shortcuts import render
from kubernetes import client, config
from django.core.cache import cache
from django.conf import settings
import redis
from django.db.models import Q
from django.http import HttpResponse
from django.views import View
from app import models
import pandas as pd
import os
import time
from rest_framework.authtoken.models import Token
from django_redis import get_redis_connection

from .utils.aliyun_sms import Aliyun
from .utils.email import EmailUtil
from .utils.image import resize_image_with_max_dimensions, read_image
from .utils.k8s.kubenetesManager import KubernetesManager
from .utils.k8s.kubePrometheus import KubeScheduling
from .utils.mimetypes import MimeTypes
from .utils.pdf_content_pos import PdfContentPosition
from .utils.serializers import (
    SendSMSCodeSerializer,
	MobileLoginSerializer,
)
# 在你的Django项目的某个应用中的views.py文件中
import pytz
from docker import DockerClient
'''
基础处理类，其他处理继承这个类
'''
redis_host = '172.20.216.103'
redis_port = 30000 # k8s容器端口6379， 暴露到外面的服务是30000
namespace = 'current-semester'

def get_file_base64(file_path)->str:
    """
    获取文件的MIME类型
    :return: data:xxxxxxxx;base64,xxxxxxxx 格式的base64字符串
    """
    mt = MimeTypes()
    mime_type, _ = mt.guess_type(url=file_path)
    with open(file_path, 'rb') as file:
        # 读取文件内容并进行base64编码
        file_content = file.read()
        encoded_content = base64.b64encode(file_content).decode('utf-8')
    
    # 返回文件的base64前缀和MIME类型
    return f"data:{mime_type};base64,{encoded_content}"

def get_file_base64_prefix_type(file_path)->str:
    """
    Args:
        file_path (str): 根据文件后缀来获取文件的MIME类型

    Returns:
        str: mime_type
    """
    # 获取文件的MIME类型
    mt = MimeTypes()
    mime_type, _ = mt.guess_type(url=file_path)
    with open(file_path, 'rb') as file:
        # 读取文件内容并进行base64编码
        file_content = file.read()
        encoded_content = base64.b64encode(file_content).decode('utf-8')
    
    # 返回文件的base64前缀和MIME类型
    return f"data:{mime_type};base64"

def getTaskTeachingSourceDir(course_id:int, task_id:int, task_type:str)->str:
    """根据课程ID、作业ID、作业类型，获取作业的教学资源目录
    
    Args:
        course_id (int): 课程Id
        task_id (int): 任务Id
        task_type (str): 任务类型（homework、exam、experiment）
        
    Returns:
        str: _description_
    """

    homework_dir = os.path.join(settings.FILE_ROOT,str(course_id), f'{task_type}{task_id}','teachingSource')
    # 如果不存在，那么创建该目录
    if not os.path.exists(homework_dir):
        os.makedirs(homework_dir)
    return homework_dir

def getTaskStuSubmitDir(course_id, task_id, user_id, task_type):
    homework_dir = os.path.join(settings.FILE_ROOT,str(course_id), f'{task_type}{task_id}','stuSubmit',str(user_id))
    if not os.path.exists(homework_dir):
        os.makedirs(homework_dir)
    return homework_dir


def chinatime2utc(time_str:str)->datetime:
    """ 
    将字符串转换为 datetime 对象，假设中国时间是以东八区为准的，即 'Asia/Shanghai'

    Args:
        time_str (str): 时间字符串

    Returns:
        datetime: _description_
    """
    china_time = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
    china_timezone = pytz.timezone('Asia/Shanghai')
    china_time = china_timezone.localize(china_time)

    # 将中国时间转换为美国东部时间
    us_eastern_timezone = pytz.timezone('America/New_York')
    us_eastern_time = china_time.astimezone(us_eastern_timezone)
    return us_eastern_time

def getTimeOffset(start_time_str:str, end_time_str:str)->int:
    """
    判断时间是否超出当前时间

    Args:
        start_time_str (str): 开始时间
        end_time_str (str): 结束时间

    Returns:
        int: 在范围之前返回-1，在范围之内返回0，超过范围返回1
    """

    now_time = datetime.now()
    try:
        start_time = datetime.strptime(start_time_str, '%Y-%m-%dT%H:%M:%S.%fZ')
    except Exception as e:
        start_time = chinatime2utc(start_time_str)
    try:
        end_time = datetime.strptime(end_time_str, '%Y-%m-%dT%H:%M:%S.%fZ')
    except Exception as e:
        end_time = chinatime2utc(end_time_str)

    # 将start_time和end_time统一为东部时间
    start_time = start_time.astimezone(pytz.timezone('America/New_York'))
    end_time = end_time.astimezone(pytz.timezone('America/New_York'))
    
    now_time = datetime.now(pytz.timezone('America/New_York'))


    if now_time < start_time:
        return -1
    elif now_time > end_time:
        return 1
    else:
        return 0

def ustime2cntime(us_time:datetime )->str:
    """
    美国时间转中国时间
    
    Args:
        us_time (datetime): _description_

    Returns:
        str: _description_
    """
    if us_time ==None:
        return None
    cn_time = timezone.localtime(us_time, timezone=timezone.get_current_timezone())
    cn_time_str = cn_time.strftime(settings.DATETIME_FORMAT)
    
    return cn_time_str

def set_token(name:str, token:str)->None:
    """
    将token保存到Redis

    Args:
        name (str): token key
        token (str): token value
    """
    r = redis.StrictRedis(host=redis_host, port=redis_port, decode_responses=True)
    
    # 保存token
    r.set(name, token)
    
def get_token(name:str)->str:
    """
    从Redis获取token

    Args:
        name (str): token key

    Returns:
        str: token value
    """
    r = redis.StrictRedis(host=redis_host, port=redis_port, decode_responses=True)
    return r.get(name)

def verifySms(name:str, sms:str)->bool:
    """
    验证短信验证码

    Args:
        name (str): token key
        sms (str): 验证码

    Returns:
        bool: 验证结果
    """
    stored_sms = cache.get(name)
    if stored_sms == None:
        return "请重新获取验证码"
    if stored_sms == sms:
        return True
    else:
        return "验证码错误"
# def is_chinese(input_str):
#     # 判断是否为中文姓名
#     return len(input_str) > 0 and (
#                 bool(re.match('^[\u4e00-\u9fa5]+$', input_str)) or bool(re.match('^[a-zA-Z]+$', input_str)))
#
#
# def is_student_id(input_str):
#     # 判断是否为学号（包含数字和字母）
#     return len(input_str) > 0 and bool(re.match('^[0-9a-zA-Z]+$', input_str))


class ParamView(View):
    '''
    获取请求参数
    '''
    def getStudentNamespace(self):
        '''
        获取学生命名空间
        '''
        namespace = models.DefaultParams.objects.filter(param_name='working_namespace')
        if namespace.exists():
            return namespace.first().param_value
        else:
            models.DefaultParams.objects.create(param_name='working_namespace', 
                                                param_value='current-semester',
                                                 param_type='string',
                                                 is_static=True)
            
            return 'current-semester'
    
    def getDefaultClusterIP(self):
        '''
        获取默认集群IP
        '''
        default_cluster_ip = models.DefaultParams.objects.filter(param_name='集群IP')
        if default_cluster_ip.exists():
            default_cluster_ip = default_cluster_ip.first().param_value
        else:
            models.DefaultParams.objects.create(
                param_name='集群IP',
                param_value='172.20.216.103',
                param_type='string',
                is_static=True,
            )
            default_cluster_ip = '172.20.216.103'
        return default_cluster_ip
class BaseView(View):
    '''
    成功响应信息
    '''
    def success(msg='处理成功'):
        resl = {'code': 200, 'msg': msg}
        return HttpResponse(json.dumps(resl), content_type='application/json; charset=utf-8', status=200)

    '''
    成功响应信息, 携带数据
    '''
    def successData(data, msg='处理成功'):
        resl = {'code': 200, 'msg': msg, 'data': data}  # 字典
        return HttpResponse(json.dumps(resl), content_type='application/json; charset=utf-8', status=200)

    '''
    系统警告信息
    '''
    def warn(msg='操作异常，请重试'):
        resl = {'code': 1, 'msg': msg}
        return HttpResponse(json.dumps(resl), content_type='application/json; charset=utf-8', status=200)

    '''
    系统异常信息
    '''
    def error(msg='系统异常'):
        resl = {'code': 2, 'msg': msg}
        return HttpResponse(json.dumps(resl), content_type='application/json; charset=utf-8', status=500)
    
    '''
    检查指定的参数是否存在
    存在返回 True
    不存在返回 False
    '''

    def isExit(param):
        if (param == None) or (param == ''):
            return False
        else:
            return True

    '''
    转换分页查询信息
    '''
    def parasePage(pageIndex, pageSize, pageTotal, count, data):
        return {'pageIndex': pageIndex, 'pageSize': pageSize, 'pageTotal': pageTotal, 'count': count, 'data': data}



class TeacherView(BaseView):
    
    def post(self, request, module, *args, **kwargs):
        if module == 'getTeacherInfo':
            return TeacherView.getTeacherInfo(request)
        elif module == 'updateTeacherInfo':
            return TeacherView.updateTeacherInfo(request)
        elif module == 'getTeacherList':
            return TeacherView.getTeacherList(request)
        else:
            return BaseView.success()
        
    def checkSetAllInfo(user_id):
        '''
        检查教师信息是否完整
        '''
        teacher = models.Teacher.objects.filter(user_id=user_id).first()
        if teacher.name == '' or teacher.name == None:
            return '请输入真实姓名'
        if teacher.gender==None or teacher.gender == '':
            return '请选择性别'
        if teacher.school==None or teacher.school == '':
            return '请选择学校'
        if teacher.college==None or teacher.college == '':
            return '请选择学院'
        if teacher.phone_number==None or teacher.phone_number == '':
            return '请输入手机号'
        return True
    
    def getTeacherList(request):
        """
        获取教师列表
        """
        try:
            params = getParam(request)
            page_index = int(params['page_index'])
            page_size = int(params['page_size'])
            name = params['name']
            college = params['college']
            school = params['school']
            teacher_list = models.Teacher.objects.all()
            if name:
                teacher_list = teacher_list.filter(name__icontains=name)
            if college:
                teacher_list = teacher_list.filter(college__icontains=college)
            if school:
                teacher_list = teacher_list.filter(school__icontains=school)
            count = teacher_list.count()
            page_total = (count + page_size - 1) // page_size
            teacher_list = teacher_list[(page_index - 1) * page_size:page_index * page_size]
            data = []
            for tea in teacher_list:
                data.append({
                    "phone_numbers": tea.phone_number,
                    "name": tea.name,
                    "nickName": tea.name,
                    "gender": tea.gender,
                    "birthday": tea.birthday,
                    "school": tea.school,
                    "college": tea.college,
                    "id": tea.user_id,
                    "email": tea.email,
                })
            return BaseView.successData(data, {"page_index": page_index, "page_size": page_size, "page_total": page_total, "count": count})
        except Exception as e:
            return BaseView.error()

    def getTeacherInfo(request):
        """
        获取教师信息
        """ 
        user_id = getParam(request)['user_id']
        tea = models.Teacher.objects.filter(user_id=user_id).first()
        data = {
                "phone_numbers": tea.phone_number,
                "name": tea.name,
                "nickName": tea.name,
                "gender": tea.gender,
                "birthday": tea.birthday,
                "school": tea.school,
                "college": tea.college,
                "id": tea.user_id,
                "email": tea.email,
            }
        return BaseView.successData(data)
    
    def updateTeacherInfo(request):
        '''
        更新教师信息
        '''
        try:
            params = getParam(request)
            gender = params['gender']
            birthday = params['birthday']
            school = params['school']
            college = params['college']
            name = params['name']
            user_id = params['id']
            email = params['email']
            phone_numbers = params['phone_numbers']
            models.Teacher.objects.filter(user_id=user_id).update(
                gender=gender,
                birthday=birthday,
                school=school,
                college=college,
                name=name,
                phone_number=phone_numbers,
                email=email,
            )
            return BaseView.success()
        except Exception as e:
            # print (e)
            return BaseView.error()
        
class FileView(BaseView):
    
    def post(self, request, module, *args, **kwargs):
        if module == 'setAvatar':
            return FileView.setAvatar(request)
        elif module == 'getAvatar':
            return FileView.getAvatar(request)
        elif module == 'getSelectedStudentFile':
            return FileView.getSelectedStudentFile(request)
        elif module == 'getSelectedTeacherFile':
            return FileView.getSelectedTeacherFile(request)
        else :
            return BaseView.error("请检查路由路径")
        
    def copy_file(self, src_file, dest_file):
        '''
        复制文件
        '''
        if not os.path.exists(src_file):
            return False
        shutil.copy(src_file, dest_file)
        return True
    def getSelectedTeacherFile(request):
        '''
        获取选中的教师文件
        '''
        try:
            params = getParam(request)
            task_id = params['task_id']
            file_name = params['file_name']
            
            file_path = ''
            file_type = ''

            task_files = models.TaskFiles.objects.filter(task_id=task_id)
            for task_file in task_files:
                if file_name == os.path.basename(task_file.file.name):
                    file_path = task_file.file.name
                    file_type = task_file.file_type
                    break

            
            if os.path.exists(file_path):
                base64_data=''
                
                with open(file_path, 'rb') as f:
                    content = str(base64.b64encode(f.read()))
                    if content.startswith('b\''):
                        content = content[2:-1]
                    base64_data = file_type +',' +content
                    return BaseView.successData(base64_data)
            return BaseView.warn("获取文件失败")
        except Exception as e:
            # print (e)
            return BaseView.error()

    def getSelectedStudentFile(request):
        '''
        获取选中的学生文件
        '''
        try:
            params = getParam(request)
            task_id = params['task_id']
            user_id = params['user_id']
            file_name = params['file_name']

            student = models.Student.objects.get(user_id=user_id)
            file_path = ''
            task = models.Task.objects.get(task_id=task_id)
            task_submits = task.submissions.filter(student=student)
            file_type = ''
            for task_submit in task_submits:
                if file_name == os.path.basename(task_submit.submit_file.name):
                    file_path = task_submit.submit_file.name
                    file_type = task_submit.file_type
                    if file_path.endswith('.pdf') and  task_submit.marked_file:
                        file_path = task_submit.marked_file.name
                        # file_type = task_submit.file_type
                    if not os.path.exists(file_path):
                        return BaseView.warn("文件不存在")
                    break
            if file_path:
                base64_data=''
                # 处理ipynb文件
                if file_path.endswith('.ipynb'):
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = json.load(f)
                        return BaseView.successData({'file_content':content})
                pos = ''
                if file_path.endswith('.pdf'):
                    pdfPosGetter = PdfContentPosition()
                    pos = pdfPosGetter.get_content_pos(file_path)
                with open(file_path, 'rb') as f:
                    content = str(base64.b64encode(f.read()))
                    if content.startswith('b\''):
                        content = content[2:-1]
                    base64_data = file_type + "," + content
                    return BaseView.successData({'file_content':base64_data, 'pos':pos})
            return BaseView.warn("获取文件失败")
        except Exception as e:
            print(e)
            return BaseView.error()
        
    def setAvatar(request):
        '''
        设置头像
        '''
        params = getParam(request)
        avatar = params['avatar']
        user_id = params['user_id']

        try:
            file_dir = os.path.join(settings.MEDIA_ROOT,'avatars')
            file_path = os.path.join(file_dir,"avatar_"+user_id+".png")
            os.path.exists(file_dir) or os.makedirs(file_dir)

            base64_data = avatar.split(",")[1]  # 去除"data:image/png;base64,"部分
            image_data = base64.b64decode(base64_data)
            with open(file_path, 'wb+')as destination:
                destination.write(image_data)
            user = models.Account.objects.filter(user_id=user_id).first()
            user.avatar = os.path.realpath(file_path)
            user.save()
            return BaseView.success()
        except Exception as e:
            print("出错",e)
            return BaseView.error(e)
        
 
    def getAvatar(request):
        '''
        获取头像
        '''
        user_id = getParam(request)['user_id']
        try:
            user = models.Account.objects.get(user_id=user_id)            
            if user.avatar:# 如果存在头像，那么使用改头像
                file_path = str(user.avatar)
            else:
                file_path=os.path.join(settings.PROJECT_MEDIA_ROOT,"avatars/avatar_default.png")
            return BaseView.successData(read_image(file_path))
          
        except Exception as e:
            print("出错,原因：",e)
            return BaseView.error(e)


    def getAvatarUrl(self, user_id=None):
        '''
        获取头像url
        '''
        try:
            user = models.Account.objects.get(user_id=user_id)
            if user.avatar:# 如果存在头像，那么使用改头像
                file_path = str(user.avatar)
            else:
                file_path=os.path.join(settings.PROJECT_MEDIA_ROOT,"avatars/avatar_default.png")
                # print("默认头像路径：" + file_path)
            return 'http://172.20.216.103:8000/media/avatars/'+file_path.split('/')[-1]
          
        except Exception as e:
            print("getAvatarUrl出错,原因：",e)
            return BaseView.error(e)

    def setCover(file:str, course:models.Course):
        '''
        设置课程封面
        '''
        try:
            dir_path = os.path.join(settings.MEDIA_ROOT,'covers')
            os.path.exists(dir_path) or os.makedirs(dir_path)
            
            relative_path = os.path.join('covers/',"cover_"+str(course.course_id)+".png")
            file_path=os.path.join(settings.MEDIA_ROOT,relative_path)
            base64_data = file.split(",")[1]  # 去除"data:image/png;base64,"部分
            image_data = base64.b64decode(base64_data)
            with open(file_path, 'wb+')as destination:
                destination.write(image_data)
            # user = models.Course.objects.filter(course_id=course_id).first()
            course.course_cover = os.path.realpath(file_path)
            course.save()
            return relative_path
        except Exception as e:
            print("出错",e)
            return None

    
    def getShinkedCover(course:models.Course, max_width, max_height):
        '''
        获取缩略图封面
        '''
        try:
            if course.course_cover and course.course_cover!='':# 如果存在封面，那么使用改封面
                file_path = str(course.course_cover)
            elif course.imported_from_course_id and course.imported_from_course_id!='':
                course = models.Course.objects.get(course_id=course.imported_from_course_id)
                if course.course_cover and course.course_cover!='':
                    file_path = str(course.course_cover)
                else:
                    file_path=os.path.join(settings.PROJECT_MEDIA_ROOT,"covers/cover_default.png")
            else:
                file_path=os.path.join(settings.PROJECT_MEDIA_ROOT,"covers/cover_default.png")

            return resize_image_with_max_dimensions(input_path=file_path,  max_width=max_width, max_height=max_height)
        except Exception as e:
            print("getShinkedCover出错,原因：",e)
            return None
    def deleteCover(course:models.Course):
        '''
        删除课程封面
        '''
        try:
            if course.course_cover:# 如果存在封面，那么使用改封面
                file_path = str(course.course_cover)
                os.remove(file_path)
                course.course_cover = None
                course.save()
            return True
        except Exception as e:
            print("删除封面失败，原因：",e)
            return False

class UserView(BaseView):

    def post(self, request, module, *args, **kwargs):


        if module == 'loginOut':
            return UserView.loginOut(request)
        elif module == 'login':
            return UserView.login(request)
        # elif module == 'getLoginToken':
        #     return UserView.getLoginToken(request)
        elif module == 'info':
            return UserView.getInfo(request)
        # 邮箱验证码
        elif module == 'send_email_code':
            return UserView.send_email_code(request)
        # 手机验证码
        elif module =='send_sms_code':
            return UserView.send_sms_code(request)
        elif module =='register':
            return UserView.register(request)
        # 获取学校、学院、专业
        elif module == 'getAllSchool':
            return UserView.getAllSchool(request)
        elif module == 'getCollegeBySchool':
            return UserView.getCollegeBySchool(request)
        elif module == 'getMajorByCollege':
            return UserView.getMajorByCollege(request)
        # 修改密码
        elif module =='verifyPassword':
            return UserView.verifyPassword(request)
        elif module =='changePassword':
            return UserView.changePassword(request)
        # 修改手机号
        elif module == 'changePhoneNumber':
            return UserView.changePhoneNumber(request)
        # 修改邮箱
        elif module == 'changeEmail':
            return UserView.changeEmail(request)
        elif module == 'sendHeartbeat':
            return UserView.sendHeartbeat(request)
        elif module == 'fetchOnlineUsers':
            return UserView.fetchOnlineUsers(request)
        elif module == 'detectAccountInfo':
            return UserView.detectAccountInfo(request)
        else:
            return BaseView.error("请检查路由路径")
    
    def detectAccountInfo(request):
        '''
        检测账户信息
        '''
        try:
            params = getParam(request)
            user_id = params['user_id']
            is_teacher = params['is_teacher']
            is_super = params['is_super']
            account = models.Account.objects.filter(user_id=user_id).first()
            if account.password == '123456':
                return BaseView.successData({
                    'code':1,
                    'msg':'检测到初始密码，请修改密码'})
            if is_teacher:
                user = models.Teacher.objects.filter(user_id=user_id).first()
            else:
                user = models.Student.objects.filter(user_id=user_id).first()
          
            return BaseView.successData({'code':0,})

        except Exception as e:
            return BaseView.error(e)
    
    
    def fetchOnlineUsers(request):
        try:
            params = getParam(request)
            page = int(params['page'])
            pageSize = int(params['pageSize'])
            query = params['query']
            
            
            now = timezone.now()
            onlineUsers = cache.get('onlineUsers')
            if onlineUsers == None:
                onlineUsers = {}
            online_users = []
            user_ids = list(onlineUsers.keys())
            
            for user_id in user_ids[(page-1)*pageSize:page*pageSize]:
                # online_users.append({'user_id':user_id, 'name':user_id})
                user_data = onlineUsers[user_id]
                if (now - user_data['last_seen']).seconds < 120:
                    # pass
                    online_users.append({
                        'user_id':user_id, 
                        'name':user_id, 
                        'last_seen': timezone.localtime(user_data['last_seen']).strftime('%Y-%m-%d %H:%M:%S'), 
                        'ip':user_data['ip'], 
                        'visitorId':user_data['visitorId'], 
                        'login_time': timezone.localtime(user_data['login_time']).strftime('%Y-%m-%d %H:%M:%S'), 
                        })
                else:
                    onlineUsers.pop(user_id)
            lastUpdateTime = timezone.localtime().strftime('%Y-%m-%d %H:%M:%S')
            # 更新缓存
            cache.set('onlineUsers', onlineUsers, timeout=120)  # 1分钟超时
            # return BaseView.success()
            return BaseView.successData({'onlineUsers':online_users, 'total':len(user_ids),'lastUpdateTime':lastUpdateTime })
        except Exception as e:
            # print("onlineUsers出错,原因：",e)
            return BaseView.warn(e)
    
    def sendHeartbeat(request):
        try:
            params = getParam(request)
            ip = params['ip']
            visitorId = params['visitorId']
            user_id = params['user_id']
            
            account = models.Account.objects.filter(user_id=user_id)
            if account.count() == 0:
                return BaseView.error("用户不存在")
            account = account.first()

            if account.is_super or account.is_teacher:
                return BaseView.success()
            
            check_unique = None
            if 'check_unique' in params.keys():
                check_unique = params['check_unique'] # 登录的时候需要检查一次。
            print("ip:",ip,"visitorId:",visitorId,"user_id:",user_id)
            now = timezone.now()
            
            onlineUsers = cache.get('onlineUsers')
            if onlineUsers == None:
                onlineUsers = {}
            if user_id not in onlineUsers.keys():
                user_data = {
                    'user_id': user_id,
                    'ip': ip,
                    'visitorId': visitorId,
                    'login_time': now,
                    'last_seen': now,
                }
                onlineUsers[user_id] = user_data
            else:
                user_data = onlineUsers[user_id]
                user_data['last_seen'] = now
            
            # 更新缓存
            cache.set('onlineUsers', onlineUsers, timeout=120)  # 2分钟在线缓存
            # 需求1：在线考试时，用户在一台电脑上只能登录一个账号。如果检测到同一台电脑登录多个账号，则返回错误信息。
            # 需求2（未实现，实现不了）：一个用户不能在多台设备登录。需要判断手机、电脑、IP、浏览器，很可能会误禁登录。
            if check_unique!=None and check_unique==True :
                for user_id2 in onlineUsers.keys():
                    if user_id != user_id2 :
                        user_data = onlineUsers[user_id2]
                        if user_data['visitorId']==visitorId or user_data['ip']==ip :
                            models.LoginConfliction.objects.create(
                                user_id_old=user_id2, 
                                user_id_new=user_id,
                                ip_old=user_data['ip'],
                                ip_new=ip,
                                visitorId_old=user_data['visitorId'],
                                visitorId_new=visitorId,
                                )
                            return BaseView.warn('同一台电脑登录多个账号')
            return BaseView.success()
        except Exception as e:
            print("heartbeat出错,原因：",e)
            return BaseView.warn(e)
            
    def login(request):

        data = getParam(request)
        userName = data.get('id')
        passWord = data.get('passWord')
        ip = data.get('ip')
        visitorId = data.get('visitorId')
        
        print('login userName:', userName, 'passWord:', passWord, 'ip:', ip, 'visitorId:', visitorId)
        user = models.Student.objects.filter(user_id=userName)
        acc = models.Account.objects.filter(user_id=userName)
        try:
            # 如果是学生（用户和账户信息同时存在），或者是老师（只有账户信息且是老师）
            if ((user.exists() and acc.exists()) or (
                    acc.exists() and (acc.first().is_teacher or acc.first().is_super))):

                acc = acc.first()
                if acc.password == passWord:

                    token = uuid.uuid4()
                    # 记录用户信息
                    login_user = {
                        'user_id': acc.user_id,
                        'passWord': acc.password,
                        'is_super': acc.is_super,
                        'is_teacher': acc.is_teacher,
                        'locked': acc.locked,
                    }
                    # 返回前端的数据
                    resl = {
                        'user_id': acc.user_id,
                        'token': str(token),
                        'is_super': acc.is_super,
                        'is_teacher': acc.is_teacher
                    }
                    # 实际上我在前端使用了cookies失效时间是1天，这里是否多余？
                    # 将token保存到Redis
                    set_token('login-'+str(acc.user_id), str(token))
                    cache.add(str(token), login_user, 60 * 60 * 24 * 1) # 1天
                    models.LoginJournal.objects.create(user_id=userName, ip=str(ip), visitorId=str(visitorId), login_time=timezone.now())
                    # print("登录成功", resl)
                    return BaseView.successData(resl)
                else:
                    return BaseView.warn('用户密码输入错误')
            else:
                return BaseView.warn('用户名输入错误')
        except Exception as e:
            print(e)
            return BaseView.error(str(e))

    
 
    def loginOut(request):
        try:
            return BaseView.success()
        except Exception as e:
            return BaseView.error(e)
        
    def changeEmail(request):
        try:
            params = getParam(request)
            user_id = params['user_id']
            email = params['email']
            is_teacher = params['is_teacher']
            sms = params['sms']
            
            res = verifySms(email+user_id, sms)
            if res != True:
                return BaseView.warn(res)
            
            
            if is_teacher==True or is_teacher=='true':
                models.Teacher.objects.filter(user_id=user_id).update(email=email)
            else:
                models.Student.objects.filter(user_id=user_id).update(email=email)
            cache.delete(email+user_id)
            return BaseView.success()
        except Exception as e:
            print("修改邮箱失败，原因：",e)
            return BaseView.error(e)
        
    def send_email_code(request):
        try:
            params = getParam(request)
            email = params['email']
            email_type = params['email_type']
            user_id = params['user_id']
            stored_sms = EmailUtil.send_code_email(email, email_type)
            print('views.py send_email_code 验证码：',stored_sms)
            if  stored_sms == None:
                return BaseView.warn('发送邮箱验证码失败')
            cache.set(email+user_id, stored_sms, 60*5)   # 设置mobile:sms键值对，有效期为5分钟
            return BaseView.successData('发送邮箱验证码成功')
        except Exception as e:
            return BaseView.error('出错：'+e)
        
        
    def changePassword(request):
        params = getParam(request)
        user_id = params['user_id']
        password = params['password']
        email = params['email']
        sms = params['sms']
        res = verifySms(email+user_id, sms)
        if res != True:
            return BaseView.warn(res)
        try:
            models.Account.objects.filter(user_id=user_id).update(password=password)
            cache.delete(email+user_id)
            return BaseView.success()
        except Exception as e:
            return BaseView.error(e)
        
    def changePhoneNumber(request):
        try:
            params = getParam(request)
            user_id = params['user_id']
            is_teacher = params['is_teacher']
            phone_numbers = params['phone_numbers']
            
            if is_teacher==True or is_teacher=='true':
                models.Teacher.objects.filter(user_id=user_id).update(phone_number=phone_numbers)
            else:
                models.Student.objects.filter(user_id=user_id).update(phone_number=phone_numbers)
            return BaseView.success()
        except Exception as e:
            print("修改手机号失败，原因：",e)
            return BaseView.error(e)
    def verifyPassword(request):
        params = getParam(request)
        pwd = params['password']
        user_id=params['user_id']
        student = models.Account.objects.filter(user_id=user_id).first()
        if student.password == pwd:
            return BaseView.successData(True)
        else:
            return BaseView.successData(False)

    def getAllSchool(request):
        try:
            schools = list(set(models.SchoolCollegeMajor.objects.values_list('school', flat=True)))
            print('getAllSchool', schools)
            return BaseView.successData(schools)
        except Exception as e:
            return BaseView.error('数据库出错')
        
    def getCollegeBySchool(request):
        school = getParam(request)['school']
        try:
            colleges = list(set( models.SchoolCollegeMajor.objects.filter(school=school).values_list('college', flat=True)))
            print('colleges = ', colleges)
            return BaseView.successData(colleges)
        except Exception as e:
            return BaseView.error('数据库错误')
        
    def getMajorByCollege(request):
        params = getParam(request)
        school = params['school']
        college = params['college']
        majors = list(set( models.SchoolCollegeMajor.objects.filter(school=school, college=college).values_list('major', flat=True)))

        print("majors = ", majors)
        return BaseView.successData(majors)
    
    def send_sms_code(request):
        params = getParam(request)
        phone_numbers = params['phone_numbers']

        # 生成随机验证码，发送验证码并将其保存到数据库中
        stored_sms = random.randrange(100000, 999999)
        sign_name='重庆大学大数据教学平台',
        template_code='SMS_465363041',
        res = Aliyun.send_sms(phone_numbers=phone_numbers, template_code=template_code,code=stored_sms,sign_name=sign_name)
        if '只能向已回复授权信息的手机号发送' in str(res):
            return BaseView.warn('只能向已回复授权信息的手机号发送')
        cache.set(str(phone_numbers), stored_sms, 60*5)   # 设置mobile:sms键值对，有效期为5分钟
        return BaseView.successData({'detail': 'Verification code sent successfully'})
    
    def register(request):
        params = getParam(request)
        # phone_number = params['phone_numbers']
        email = params['email']
        user_id = params['user_id']
        name = params['name']
        password = params['password']
        sms = params['sms']
        is_teacher = params['is_teacher']
        is_super = params['is_super']
        print(params)
        # pass掉了手机验证码注册，把下面的5个email换成phone_number就是手机验证码注册
        cached_sms = cache.get(str(email))
        print('验证码：',sms,'\n缓存里的验证码：',cached_sms)
        if cached_sms and str(cached_sms)!=str(sms):
            return BaseView.warn('验证码错误')
        if cached_sms and str(cached_sms)==str(sms):
            try:
                models.Account.objects.create(
                    user_id=user_id,
                    password=password,
                    is_teacher=is_teacher,
                    locked=0,
                    is_super=is_super)
                if is_teacher==0:
                    models.Student.objects.create(
                        user_id=user_id,
                        email=email,
                        name=str(user_id),
                        gender='男',
                        # college=account['college'],
                        # major=account['major'],
                        # cls=int(account['cls'][:-1]),
                    )
                else:
                    models.Teacher.objects.create(
                        user_id=user_id, 
                        email=email,
                        name=str(user_id),
                        gender='男',
                        # name=name, 
                        # college=college
                        )
                return BaseView.success()
            except Exception as e:
                print('注册账号失败，原因：', e)
                return BaseView.error(e)
        return BaseView.warn('验证码过期，请重新获取验证码')
    def mobile_login(request):
        # params = getParam(request)
        phoneNumber = getParam(request)

        serializer = MobileLoginSerializer(data={"mobile":phoneNumber})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        if time.time() - token.created.timestamp() > settings.TOKEN_EXPIRE_SECONDS:
            Token.objects.filter(user_id=user.id).delete()
            token, created = Token.objects.get_or_create(user=user)
        return BaseView.successData({'token': token.key,'userId': user.username,})

    def getInfo(request):
        # 尽管返回数据为空， 但是别删这个函数。删了就会出问题。
        print(request.body)
        resl = {
        }

        return BaseView.successData(resl)
    
    # 获取头像所在路径
    def get_avatar_path(user_id):
        try:
            account = models.Account.objects.get(user_id=user_id)
            if account.avatar:
                avatar_path = account.avatar.url
            else:
                # 如果头像为空，则返回默认头像路径
                avatar_path = settings.DEFAULT_AVATAR_URL
            return avatar_path
        except  models.Account.DoesNotExist:
            return None
        
        
    def profile(request):
        # 获取当前登录用户的学号
        user_id = request.user.username

        # 根据学号查询对应的头像路径
        avatar_url = UserView.get_avatar_path(user_id)

        return render(request, 'profile.html', {'avatar_url': avatar_url})
    


def getParam(request) -> dict:
    return json.loads(request.body.decode('utf-8'))

    json_data = json.loads(request.body.decode('utf-8'))
    # 遍历 JSON 对象中的每个键值对，对值进行解码
    for key, value in json_data.items():
        if isinstance(value, str):
            json_data[key] = value.decode('utf-8')

    return json_data


class StudentView(BaseView):



    def post(self, request, module, *args, **kwargs):

        if module =='getStudentInfo':
            return StudentView.getStudentInfo(request)
        # 更新学生信息
        elif module =='updateStudentInfo':
            return StudentView.updateStudentInfo(request)
        else:
            return BaseView.error()

    def checkSetAllInfo(user_id):
        try:
            user = models.Student.objects.filter(user_id=user_id).first()
            if user.name == None or user.name == '' :
                return '请输入真实姓名'
            if user.gender == None or user.gender == '':
                return '请选择性别'
            if user.birthday == None or user.birthday == '':
                return '请填写生日'
            if user.school == None or user.school == '':
                return '请选择学校'
            if user.college == None or user.college == '':
                return '请选择学院'
            if user.major == None or user.major == '':
                return '请选择专业'
            if user.phone_number == None or user.phone_number == '':
                return '请填写手机号'
            return True
        except Exception as e:
            print("出错", e)
            return False

    
    def updateStudentInfo(request):
        params = getParam(request)
        gender = params['gender']
        birthday = params['birthday']
        school = params['school']
        college = params['college']
        major = params['major']
        name = params['name']
        user_id = params['user_id']
        email = params['email']
        phone_numbers = params['phone_numbers']
        models.Student.objects.filter(user_id=user_id).update(
            gender=gender,
            birthday=birthday,
            school=school,
            college=college,
            major=major,
            name=name,
            phone_number=phone_numbers,
            email=email,
        )
        return BaseView.success()





    # def Farewell(request):
    #     token = request.POST.get('token')
    #     if not cache.get(token):
    #         return BaseView.error('尚未登录或登陆状态异常')
    #     # 退出登录
    #     cache.delete(token)
    #     return BaseView.success('退出登录成功')
  



    # def Farewell(request):
    #     token = request.POST.get('token')
    #     if not cache.get(token):
    #         return BaseView.error('尚未登录或登陆状态异常')
    #     # 退出登录
    #     cache.delete(token)
    #     return BaseView.success('退出登录成功')
    def getStudentInfo(request):
        params = getParam(request)
        user_id = params['user_id']
        stu = models.Student.objects.get(user_id=user_id)
        data = {
                "phone_numbers": stu.phone_number,
                "name": stu.name,
                "nickName": stu.name,
                "gender": stu.gender,
                "birthday": stu.birthday,
                "school": stu.school,
                "college": stu.college,
                "major": stu.major,
                "user_id": stu.user_id,
                "email": stu.email,
            }
        return BaseView.successData(data)


class SuperuserView(BaseView):
  
    def post(self, request, module, *args, **kwargs):

        # 管理员处理学生账号信息
        if module == 'getStudentAccounts':
            return SuperuserView.getStudentAccounts(request)
        elif module == 'updateStudentAccounts':
            return SuperuserView.updateStudentAccounts(request)
        elif module == 'deleteStudentAccounts':
            return SuperuserView.deleteStudentAccounts(request)
        elif module == 'addStudentAccount':
            return SuperuserView.addStudentAccount(request)

        # 管理员处理教师账号信息
        elif module == 'getTeacherAccounts':
            return SuperuserView.getTeacherAccounts(request)
        elif module == 'updateTeacherAccounts':
            return SuperuserView.updateTeacherAccounts(request)
        elif module == 'deleteTeacherAccounts':
            return SuperuserView.deleteTeacherAccounts(request)
        elif module == 'addTeacherAccount':
            return SuperuserView.addTeacherAccount(request)
        elif module == 'importStudentsFromExcel':
            return SuperuserView.importStudentsFromExcel(request)
        elif module == 'rePassword':  # 重置密码
            return SuperuserView.resetPassword(request)
        else:
            return BaseView.error("错误请求！检查url映射")

    def importStudentsFromExcel(request):
        try:
            # 需要将学生加入到班课中。如果学生账号不存在，要创建对应的账号。
            file = request.FILES.get('file')
            user_id = request.POST.get('user_id')
            course_id = request.POST.get('course_id')

            
            teacher = models.Teacher.objects.filter(user_id=user_id).first()
            stu_ids = models.Course2UserEnrollment.objects.filter(course_id=course_id).values_list('user_id', flat=True)

            if not file:
                print('importStudentsFromExcel: 后端获取文件失败')
                return BaseView.warn('请选择正确的excel文件')
            else:
                print(file.name)
            file_path = os.path.join(settings.MEDIA_ROOT, file.name)
            with open(file_path, 'wb+') as f:
                for chunk in file.chunks():
                    f.write(chunk)
            print('importStudentsFromExcel: 文件保存成功, path = ', file_path)
            data = pd.read_excel(file_path)

            user_id_index = 0
            name_index = 0
            nianji_index = 0
            college_index = 0
            major_index = 0
            cls_index = 0
            reading_type_index = 0
            school = teacher.school
            college_major = []
            # 遍历数据框的每一行
            for index, row in data.iterrows():
                # 获取每行数据
                if index == 0:
                    value = row.values.tolist()
                    user_id_index = value.index("学号")
                    name_index = value.index("姓名")
                    nianji_index = value.index("年级")
                    college_index = value.index("学院")
                    major_index = value.index("专业")
                    cls_index = value.index("行政班")
                    reading_type_index = value.index("修读性质")
                else:
                    user_id = row[user_id_index]
                    name = row[name_index]
                    nianji = row[nianji_index]
                    college = row[college_index]
                    major = row[major_index]
                    cls = row[cls_index]
                    reading_type = row[reading_type_index]
                    college_major.append((college, major))
                    # print(index, user_id, name, nianji, college, major, cls, reading_type)
                    if models.Student.objects.filter(user_id=user_id).exists() or models.Account.objects.filter(user_id=user_id).exists():
                        print(f"学号：{user_id}，已存在,不重复创建")
                    else:
                        # 创建新学生账号
                        models.Student.objects.create(
                            user_id=user_id,
                            name=name,
                            school=school,
                            college=college,
                            major=major,
                            cls=cls,
                        )
                        models.Account.objects.create(
                            user_id=user_id
                        )
                    # 学生加入课程
                    if user_id not in stu_ids:
                        print(f"学号：{user_id}，加入课程{course_id}")
                        CourseView.joinCourse(None, {'user_id': user_id, 'course_id': course_id, 'is_teacher':False})
            college_major = list(set(college_major))
            # print(college_major)
            for item in college_major:
                if not models.SchoolCollegeMajor.objects.filter(school=school,college=item[0], major=item[1]).exists():
                    print('创建学院专业', item[0], item[1])
                    models.SchoolCollegeMajor.objects.create(
                        school=school,
                        college=item[0],
                        major=item[1]
                    )
            return BaseView.success()
        except Exception as e:
            print(e)
            return BaseView.error(str(e))

    def resetPassword(request):  # 重置密码
        # 根据学号修改密码，管理员界面，无需验证
        try:
            user_id = request.POST.get("id")
            stuAccount = models.Account.objects.filter(user_id=user_id)
            if stuAccount.exist():
                stuAccount.first().update(user_id=user_id)
                return BaseView.success("重置密码成功")
            else:
                return BaseView.warn("学号不存在")
        except Exception as e:
            return BaseView.error(str(e))

    def addStudentAccount(request):

        account = getParam(request)
        print('添加学生账号', account)
        if models.Student.objects.filter(user_id=account['id']).exists():
            return BaseView.warn('学号已存在')
        default_values = {'name': 'Unknown', 'gender': 'Unknown', 'college': 'Unknown', 'major': 'Unknown', 'cls': 0}

        try:
            models.Student.objects.create(
                user_id=account['id'],
                name=account['name'] if account['name'] else account['id'],
                gender=account['gender'] if account['gender'] else '',
                college=account['college'] if account['college'] else '',
                major=account['major'] if account['major'] else '',
                cls=int(account['cls']) if account['cls'] else 0,
            )
            models.Account.objects.create(
                user_id=account['id'],
                password='123456',
                is_super=0,
                is_teacher=0,
                locked=0,
            )
        except Exception as e:
            print('添加失败')
            return BaseView.error('插入到数据库失败')
        return BaseView.success()

    def updateStudentAccounts(request):
        student_list = getParam(request)
        print("student_list = ",student_list)
        for stu in student_list:
            user = models.Student.objects.filter(user_id=stu['id'])
            if user.exists():
                try:
                    models.Student.objects.filter(user_id=stu['id']).update(
                        name=stu['name'] if stu['name'] else stu['id'],
                        gender=stu['gender'] if stu['gender'] else '',
                        school=stu['school'] if stu['school'] else '',
                        college=stu['college'] if stu['college'] else '',
                        major=stu['major'] if stu['major'] else '',
                        cls=int(stu['cls'] if stu['cls'] else 0),
                        phone_number=stu['phone']if stu['phone'] else '',
                        email=stu['email']if stu['email'] else '',
                    )
                except Exception as e:
                    print('数据库更新出错')
                    return BaseView.error(e)
        return BaseView.success()

    @classmethod
    def getStudentAccounts(cls, request):
        param = getParam(request)
        page = param.get('page')
        page_size = param.get('pageSize')
        filter_methods = param.get('filter_methods')
        selector = filter_methods['selector']  # 学院 专业 班级
        input_str = filter_methods['input_str']  # 姓名 学号

        try:
            # 构造查询条件
            query = Q()
            if selector:
                for entry in selector:
                    query |= Q(college=entry[0], major=entry[1], cls=entry[2])

            # if is_student_id(input_str):
            if len(input_str) > 0:
                query &= (Q(stu_id__icontains=input_str)
                          | Q(name__icontains=input_str)
                          | Q(phone_number__icontains=input_str))
            # elif is_chinese(input_str):
            #     query &= Q(name__icontains=input_str)
            print(Q)
            result = models.Student.objects.filter(query)
            print("过滤结果：", result)
            students = [
                {
                    'name': item.name,
                    'id': item.user_id,
                    'gender': item.gender,
                    'school': item.school,
                    'college': item.college,
                    'major': item.major,
                    'cls': item.cls,
                    'phone': item.phone_number,
                    'email': item.email} for item in result[(page - 1) * page_size:page * page_size]]

            resl = {
                'total_size': len(result),
                'data': students
            }
            return BaseView.successData(resl)

        except Exception as e:
            return BaseView.error('后端错误,' + str(e))

    @classmethod
    def deleteStudentAccounts(cls, request):
        accounts = getParam(request)
        try:
            for acc in accounts:
                t1 = models.Student.objects.filter(user_id=acc['id'])
                for enrollment in models.Course2UserEnrollment.objects.all():
                    if enrollment.user_id==acc['id']:
                        return BaseView.warn(f'学号：{acc["id"]}，该学生已加入课程，不能删除')
                if t1.exists():
                    t1.delete()
                t2 = models.Account.objects.filter(user_id=acc['id'])
                if t2.exists():
                    t2.delete()

            print('删除数据成功')
            return BaseView.success()
        except Exception as e:
            print('删除数据失败')
            return BaseView.error(e)
        pass

    def addTeacherAccount(request):

        account = getParam(request)
        user_id=account['id']
        if models.Teacher.objects.filter(user_id=user_id).exists():
            return BaseView.warn('教师已存在')
        user_account = models.Account.objects.filter(user_id=user_id)
        user_stu = models.Student.objects.filter(user_id=user_id)
        user_tea = models.Teacher.objects.filter(user_id=user_id)
        print(user_tea.exists())
        # 如果已经存在该教师账号，那么直接返回添加成功。
        if user_tea.exists():
            return BaseView.success()
        # 如果要添加这个教师账号，并且这个账号已经注册，那么将学生账号转移到教师账号里面。
        if user_account.exists()  and user_stu.exists() and (not models.Teacher.objects.filter(user_id=user_id).exists()):
            # 1、修改账号权限
            user_account = user_account.first()
            user_account.is_teacher=True
            user_account.save()
            # 2、添加教师账号
            user_stu = user_stu.first()
            
            models.Teacher.objects.create(
                user_id=user_id,
                name=user_stu.name,
                gender=user_stu.gender,
                school=user_stu.school,
                college=user_stu.college,
                birthday=user_stu.birthday,
                email=user_stu.email,
                phone_number=user_stu.phone_number,
            )
            # 3、在学生表中删除。
            models.Student.objects.filter(user_id=user_id).delete()
            return BaseView.success()
        try:
            models.Teacher.objects.create(
                user_id=user_id,
                name=user_id,
            )
            models.Account.objects.create(
                user_id=account['id'],
                password='123456',
                is_super=0,
                is_teacher=1,
                locked=0,
            )
        except Exception as e:
            print('添加失败',e)
            return BaseView.warn('插入到数据库失败')
        return BaseView.success()

    def updateTeacherAccounts(request):
        teacher_list = getParam(request)
        for teacher in teacher_list:
            user = models.Teacher.objects.filter(user_id=teacher['id'])
            if user.exists():
                try:
                    models.Teacher.objects.filter(user_id=teacher['id']).update(
                        name=teacher['name'] if teacher['name'] else '',
                        gender=teacher['gender'] if teacher['gender'] else '',
                        school=teacher['school'] if teacher['school'] else '',
                        college=teacher['college'] if teacher['college'] else '',
                        phone_number=teacher['phone'] if teacher['phone'] else '',
                        email=teacher['email'] if teacher['email'] else '',
                    )
                except Exception as e:
                    print('数据库更新出错')
                    return BaseView.error(e)
        return BaseView.success()

    @classmethod
    def getTeacherAccounts(cls, request):
        param = getParam(request)
        page = param.get('page')
        page_size = param.get('pageSize')
        filter_methods = param.get('filter_methods')
        selector = filter_methods['selector']  # 学院
        input_str = filter_methods['input_str']  # 姓名 学号

        try:
            # 构造查询条件
            query = Q()
            if selector:
                for entry in selector:
                    query |= Q(college=entry[0], major=entry[1], cls=entry[2])

            # if is_student_id(input_str):
            #     query &= Q(tea_id__icontains=input_str)
            # elif is_chinese(input_str):
            #     query &= Q(name__icontains=input_str)
            if len(input_str) > 0:
                query &= (Q(tea_id__icontains=input_str)
                          | Q(name__icontains=input_str)
                          | Q(phone_number__icontains=input_str)
                          )

            print(Q)
            result = models.Teacher.objects.filter(query)
            print("过滤结果：", result)
            students = [
                {'name': item.name,
                 'id': item.user_id,
                 'gender': item.gender,
                 'school': item.school,
                 'college': item.college,
                 'school': item.school,
                 'phone': item.phone_number,
                 'email': item.email} for item in result[(page - 1) * page_size:page * page_size]]

            resl = {
                'total_size': len(result),
                'data': students
            }
            return BaseView.successData(resl)

        except Exception as e:
            return BaseView.error('后端错误,' + str(e))

    @classmethod
    def deleteTeacherAccounts(cls, request):
        accounts = getParam(request)
        print("删除的账号: accounts = ",accounts)
        try:
            for acc in accounts:
                t1 = models.Teacher.objects.filter(user_id=acc['id'])
                for course in models.Course.objects.all():
                    if course.creator==t1.first():
                        return BaseView.warn(f'工号：{acc["id"]}，该教师已创建课程，不能删除')
                # t1.delete()
                if t1.exists():
                    print("Teacher存在: ", t1)
                    t1.first().delete()
                    
                t2 = models.Account.objects.filter(user_id=acc['id'])
                if t2.exists():
                    print("Account存在: ", t2)
                    t2.first().delete()


            print('删除数据成功')
            return BaseView.success()
        except Exception as e:
            print('删除数据失败, 原因: ',e)
            return BaseView.error(e)
        pass




class ClusterView(BaseView):
    def get(self, request, module, *args, **kwargs):

        if module == 'getContainers':
            return ClusterView.getContainers(request)
        elif module == 'getClusterInfo':
            return ClusterView.get_cluster_info(request)
        elif module == 'getClusterOverview':
            return ClusterView.get_cluster_overview(request)
        elif module =='getAllNamespace':
            return ClusterView.get_all_namespace(request)
        elif module == 'getPodsLoad':
            return ClusterView.getPodsLoad(request)
        elif module == 'getDefaultParams':
            return ClusterView.getDefaultParams(request)
        elif module == 'getBackupSetting':
            return ClusterView.getBackupSetting(request)
        
    def post(self, request, module, *args, **kwargs):
        if module == 'getPods':
            return ClusterView.get_pods(request)
        elif module == 'getPodDetail':
            return ClusterView.get_pod_detail(request)
        elif module == 'createNamespace':
            return ClusterView.create_namespace(request)
        elif module == 'getPythonImages':
            return ClusterView.getPythonImages(request)
        elif module == 'goTaskContainer':
            return ClusterView.goTaskContainer(request)
        elif module == 'deletePod':
            return ClusterView.deletePod(request)
        elif module == 'duplicate_student_files':
            return ClusterView.duplicate_student_files(request)
        elif module == 'getBackupDir':
            return ClusterView.getBackupDir(request)
        elif module == 'RecoverBackupFile':
            return ClusterView.RecoverBackupFile(request)
        elif module == 'saveDefaultParams':
            return ClusterView.saveDefaultParams(request)
        elif module == 'addDefaultParam':
            return ClusterView.addDefaultParam(request)
        elif module == 'handleDeleteStaticParam':
            return ClusterView.handleDeleteStaticParam(request)
        elif module == 'ctrlSaveFiles':
            return ClusterView.ctrlSaveFiles(request)
        elif module == 'getExamStartTime':
            return ClusterView.getExamStartTime(request)

    
    def getExamStartTime(request):
        try:
            params = getParam(request)
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            exam_task = models.Task.objects.get(task_id=task_id)
            # exam_container = models.Container.objects.get(task_id=task_id, student_id=user_id)
            time_left = 0
            # end_time = timezone.localtime(exam_task.end_time, timezone=timezone.get_current_timezone())
            # if exam_container.count_down_end_time == None:
            #     exam_container.count_down_end_time = exam_task.end_time
            #     exam_container.save()

            endtime = timezone.localtime(exam_task.end_time, timezone=timezone.get_current_timezone())
            time_left =( endtime - timezone.now()).total_seconds()
            # 将时间转为毫秒
            time_left = max(time_left, 0)*1000
            
            return BaseView.successData(int(time_left))
        except Exception as e:
            print(e)
            return BaseView.error(str(e))
                  

    def ctrlSaveFiles(request):
        try:
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            task_type = params.get('task_type')
            stu_base_dir = getTaskStuSubmitDir(course_id, task_id, user_id, task_type)
            # 读取stu_base_dir下一级的文件，而不是所有文件
            file_list = os.listdir(stu_base_dir)
            file_list = [file for file in file_list if os.path.isfile(os.path.join(stu_base_dir, file))]
            print('file_list = ', file_list)
            return BaseView.successData(file_list)
            file_list = params.get('file_list')
            for file_name in file_list:
                file_path = os.path.join(stu_base_dir, file_name)
                if os.path.exists(file_path):
                    with open(file_path, 'rb') as f:
                        content = f.read()
                    return BaseView.successData(content)
                else:
                    return BaseView.warn('文件不存在')
        except Exception as e:
            return BaseView.error(str(e))
    
    
    def handleDeleteStaticParam(request):
        try:
            params = getParam(request)
            param_name = params.get('param_name')
            models.DefaultParams.objects.filter(param_name=param_name).delete()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    
    def getBackupSetting(request):
        try:
            backup_interval_minutes = models.DefaultParams.objects.filter(param_name='backup_interval_minutes')
            backup_count = models.DefaultParams.objects.filter(param_name='backup_count')
            
            if backup_count.exists():
                backup_count = int(backup_count.first().param_value)
            else:
                models.DefaultParams.objects.create(
                    param_name='backup_count',
                    param_value='5',
                    param_type='number',
                    is_static=False,
                )
                backup_count = 5
                
                
            if backup_interval_minutes.exists():
                backup_interval_minutes = int(backup_interval_minutes.first().param_value)
            else:
                models.DefaultParams.objects.create(
                    param_name='backup_interval_minutes',
                    param_value='10',
                    param_type='number',
                    is_static=False,
                )
                backup_interval_minutes = 10
                
            return BaseView.successData({
                'backup_interval_minutes': backup_interval_minutes,
                'backup_count': backup_count
            })
        except Exception as e:
            return BaseView.error(str(e))
    
    def addDefaultParam(request):
        try:
            params = getParam(request)
            param_name = params.get('param_name')
            param_value = params.get('param_value')
            param_type = params.get('param_type')
            before_name = params.get('before_name')
            is_add = params.get('is_add')
            current_params = models.DefaultParams.objects.filter(param_name=param_name)
            if is_add in [True, 'true', 'True', 1]:
                # 添加参数
                if current_params.exists():
                    return BaseView.warn('参数名已存在')
                models.DefaultParams.objects.create(
                    param_name=param_name,
                    param_value=param_value,
                    param_type=param_type,
                    is_static=True,
                )
            else:
                models.DefaultParams.objects.filter(param_name=before_name).update(
                    param_name=param_name,
                    param_value=param_value,
                    param_type=param_type,
                )     
            # if models.DefaultParams.objects.filter(param_name=param_name).exists():
            #     models.DefaultParams.objects.filter(param_name=param_name).update(
            #         param_value=param_value,
            #         param_type=param_type,
            #         is_static=False,
            #     )
            # else:
                
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    
    def getDefaultParams(request):
        try:
            params = models.DefaultParams.objects.all()
            default_params = {}
            staticParams = {}
            schoolList = list(models.SchoolCollegeMajor.objects.values_list('school', flat=True).distinct())
            print("schoolList = ", schoolList)
            for param in params.filter(is_static=False):
                default_params[param.param_name] = param.param_value
                if 'bool' in param.param_type:
                    default_params[param.param_name] = True if default_params[param.param_name] in ['1', 'True', 'true',True] else False
            for param in params.filter(is_static=True):
                staticParams[param.param_name] = param.param_value
                if 'bool' in param.param_type:
                    staticParams[param.param_name] = True if staticParams[param.param_name] in ['1', 'True', 'true',True] else False
            return BaseView.successData({
                'defaultParams': default_params,
                'schoolList':schoolList,
                'staticParams':staticParams
                                         })
        except Exception as e:

            print(e)
            return BaseView.error(str(e))
    
    
    def saveDefaultParams(request):
        try:
            params = getParam(request)
            keys = params.keys()
            for key in keys:
                item = models.DefaultParams.objects.filter(param_name=key)
                if item.exists():
                    item.update(param_value=params[key])
                else:
                    models.DefaultParams.objects.create(
                        param_name=key,
                        param_value=params[key],
                    )
            auto_scheduling = params.get('auto_scheduling')
            if auto_scheduling in ['true', 'True', True]:
                async def schedule ():
                    kubeScheduler = KubeScheduling()
                    kubeScheduler.delete_defunct_pods()
                asyncio.run(schedule())
            return BaseView.success()
        except Exception as e:
            print(e)
            return BaseView.error(str(e))
    
    def RecoverBackupFile(request): 
        try:
            params = getParam(request)
            course_id = params.get('course_id') 
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            task_type = params.get('task_type')
            recover_dir = params.get('backup_dir')
            stu_base_dir = getTaskStuSubmitDir(course_id, task_id, user_id, task_type)
            backup_dir = os.path.join(stu_base_dir, '.backup',recover_dir)
            
            # 将backup_dir下的所有文件复制到stu_base_dir下
            if not os.path.exists(stu_base_dir):
                os.makedirs(stu_base_dir)
            files = []
            for file in os.listdir(backup_dir):
                files.append(file)
                source_file = os.path.join(backup_dir, file)
                dest_file = os.path.join(stu_base_dir, file)
                if os.path.isfile(source_file):
                    shutil.copy(source_file, dest_file)
            return BaseView.successData(files)
        except Exception as e:
            return BaseView.error(str(e))
            
            
            
    def getBackupDir(request):
        try:
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            task_type = params.get('task_type')
            stu_base_dir = getTaskStuSubmitDir(course_id, task_id, user_id, task_type)
            backup_dir = os.path.join(stu_base_dir, '.backup')
            if not os.path.exists(backup_dir):
                print(f'{backup_dir} 不存在')
                return BaseView.successData([])
            
            backup_list = os.listdir(backup_dir)
            return BaseView.successData(backup_list)
        except Exception as e:
            return BaseView.error(str(e))
            
    def duplicate_student_files(request):
        try:
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            task_type = params.get('task_type')
            stu_base_dir = getTaskStuSubmitDir(course_id, task_id, user_id, task_type)
            print('备份文件： stu_base_dir = ', stu_base_dir)
            source_dir = stu_base_dir+ '/.ipynb_checkpoints'
            
            # 修改文件权限为777，防止个别时候权限不够
            file_list = os.listdir(stu_base_dir)
            file_list = [file for file in file_list if os.path.isfile(os.path.join(stu_base_dir, file))]
            print('file_list = ', file_list)
            for file_name in file_list:
                file_path = os.path.join(stu_base_dir, file_name)
                if os.path.exists(file_path):
                    os.chmod(file_path, 0o777)
                    
            # 获取最大备份次数
            backup_count = models.DefaultParams.objects.filter(param_name='backup_count')
            if backup_count.exists():
                backup_count = int(backup_count.first().param_value)
            else:
                models.DefaultParams.objects.create(
                    param_name='backup_count',
                    param_value='5',
                    param_type='number',
                    is_static=False,
                )
                backup_count = 5
            # 备份文件
            print('source_dir = ', source_dir)
            if os.path.exists(source_dir):
                
                                # 备份
                source_dir = os.path.join(stu_base_dir, '.ipynb_checkpoints')
                # 判断source_dir是否有文件，如果为空，那么跳过
                if not os.listdir(source_dir):
                    print(f'{source_dir} 为空')
                    return BaseView.success('备份文件为空，无需备份')
                
                
                duplicated_base_dir = os.path.join(stu_base_dir, '.backup')
                print("duplicated_base_dir = ", duplicated_base_dir)
                if not os.path.exists(duplicated_base_dir):
                    os.makedirs(duplicated_base_dir)
                    os.chmod(duplicated_base_dir, 0o777) 

                # 判断duplicated_base_dir里面的备份数量，超过5个则删除最早的备份
                backup_list = os.listdir(duplicated_base_dir)
                if backup_list!=None:
                    while len(backup_list) >= backup_count:
                        target_dir = os.path.join(duplicated_base_dir, backup_list[0])
                        files = os.listdir(target_dir)
                        for file in files:
                            os.remove(os.path.join(target_dir, file))
                        os.rmdir(target_dir)
                        backup_list.remove(backup_list[0])
                        print("删除最早的备份",os.path.join(duplicated_base_dir, backup_list[0]))
                        # shutil.rmtree(os.path.join(duplicated_base_dir, backup_list[0]))
                        # backup_list = os.listdir(duplicated_base_dir).sort()

                dest_dir = os.path.join(duplicated_base_dir, time.strftime('%Y%m%d%H%M%S', time.localtime()))
                shutil.copytree(source_dir, dest_dir)
                print('备份成功')
            # 还需要将用户目录当前一级所有文件保存到数据库中，供教师修改。
            # 读取stu_base_dir下一级的文件，而不是所有文件
            file_list = os.listdir(stu_base_dir)
            file_list = [file for file in file_list if os.path.isfile(os.path.join(stu_base_dir, file))]
            file_list = [os.path.join(stu_base_dir, file) for file in file_list]
            # 先获取提交的列表，将当前文件保存到数据库，将不存在的文件从数据库中删除。
            submissions = models.Task.objects.get(task_id=task_id).submissions.all()
            for file_path in file_list:
                # if submissions.filter(submit_file=str(file_path)).exists():
                #     # 1、文件路径已经记录在数据库中，不需要重复保存。
                #     print(f'{file_path} 已经记录在数据库中，跳过')
                #     continue
                # else:
                    # 2、数据库没有记录该文件，                    
                    # 将文件当做学生提交的文件，保存到数据库中
                res = TaskView.submitTask(None, {
                    "task_id": task_id, 
                    "course_id": course_id,
                    "user_id": user_id, 
                    "file_name": file_name, 
                    "task_type": task_type,
                    "file_path": file_path,
                    })
                print("添加结果: ", res)
                print(f'{file_path} 保存到数据库成功')
            # 3、数据库中有文件记录，但是文件已经不存在了，从数据库中删除。
            for submission in submissions:
                if submission.submit_file not in file_list:
                    submission.delete()
                    print(f'{submission.submit_file} 不存在，从数据库中删除')
            
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))

    def deletePod(request):
        try:
            params = getParam(request)
            namespace = params.get('namespace')
            podName = params.get('podName')
            k8sManager =KubernetesManager()
            # 根据deployment_name来匹配。如果podName以deployment_name开头，那么删除
            
            # deployment_name = '-'.join(podName.split('-')[0:3])
            container = models.Container.objects.filter(pod_name=podName)
            deploy_name = '-'.join(podName.split('-')[0:3])
            if container.exists():
                deploy_name = container.first().deployment_name
                # if deploy_name == deployment_name:
                container.delete()
            if deploy_name:
                k8sManager.delete_deploy(namespace=namespace, deploy_name=deploy_name)
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def getPodsLoad(request):
        try:
            k8sManager =KubernetesManager()
            data = k8sManager.get_pods_load()
            return BaseView.successData(data)
        except Exception as e:
            return BaseView.error(str(e))
    
    def detectExamEnd(task_id):
        try:
            exam_task = models.Task.objects.get(task_id=task_id)
            end_time = timezone.localtime(exam_task.end_time, timezone=timezone.get_current_timezone())
            now_time = timezone.localtime(timezone.now(), timezone=timezone.get_current_timezone())
            if now_time > end_time:
                return True
            else:
                return False
        except Exception as e:
            print(e)
            return False
    
    def goTaskContainer(request):
        try:
            # 创建Docker客户端
            params = getParam(request)
            print("params = ",params)
            course_id = str(params.get('course_id'))
            task_id = str(params.get('task_id'))
            user_id = str(params.get('user_id'))
            is_teacher = params.get('is_teacher')
            task_type = params.get('task_type')
            
            if task_type=='exam':
                if ClusterView.detectExamEnd(task_id):
                    return BaseView.error('考试已经结束，不能进入容器')
            # 根据作业的镜像，获取容器或者创建容器。返回容器链接，点击就能访问。
            
            task = models.Task.objects.get(task_id=task_id)
            student = models.Student.objects.get(user_id=user_id)
            container = models.Container.objects.filter(task=task, student=student)
            k8sManager =KubernetesManager()
            update_flag = False
            paramView = ParamView()
            namespace = paramView.getStudentNamespace()
            
            ingress_dir = task_type+'-'+task_id
            new_container_name = ingress_dir+'-'+user_id
            if container.exists():
                print('goTaskContainer: 数据库中存在容器记录')
                container = container.first()
            if container:
                # container = container.first()
                container.last_accessed_time = timezone.now()
                container.save()
                port = container.service_port
                token = container.token
                try:
                    service = k8sManager.get_service_info(deploy_name=new_container_name, namespace=namespace)
                    print('goTaskContainer: service: ', service)
                    pod_name = k8sManager.get_podName_by_deploy(deploy_name=new_container_name, namespace=namespace)
                    print('goTaskContainer: pod_name: ', pod_name)
                    if pod_name!= container.pod_name:
                        print('goTaskContainer: 不一致，更新')
                        update_flag = True
                        pass
                    elif service and pod_name:
                        default_cluster_ip = paramView.getDefaultClusterIP()
                        
                        url = 'http://'+default_cluster_ip+':'+str(port)+'/lab?token='+token
                        container.last_accessed_time = timezone.now()
                        container.save()
                        return BaseView.successData({'url':url})
                except Exception as e:
                    print('goTaskContainer: Exception: ', e)
                    update_flag = True
                    pass
            # else :
            # 创建容器
            print('debug 1')

            
            print('debug 2')
            teach_source_path = getTaskTeachingSourceDir(course_id, task_id, task_type)
            print('debug 3')
            stu_work_path = getTaskStuSubmitDir(course_id, task_id, user_id,task_type )
            print('debug 4')
            k8sManager.create_deployment_and_service(namespace=namespace, container_name=new_container_name, teaching_source_dir=teach_source_path,student_work_dir=stu_work_path, ingress_dir=ingress_dir)
            print('debug 5')
            
            res = k8sManager.get_pod_token(deploy_name=new_container_name, namespace=namespace)
            start = datetime.now()
            while res==None:
                # 睡眠1秒
                time.sleep(1)
                res = k8sManager.get_pod_token(deploy_name=new_container_name, namespace=namespace)
                if (datetime.now() - start).seconds > 10:
                    return BaseView.error('获取token超时')
            print('debug 6')
            token = str(res['token'])
            pod_name = res['pod_name']
            service = k8sManager.get_service_info(deploy_name=new_container_name, namespace=namespace)
            print('debug 7')
            port = service['port']
            if not update_flag:
                print('debug 8.1 ')
                print('goTaskContainer: 数据库中不存在容器记录，创建')
                models.Container.objects.create(
                    student=student,
                    task=task,
                    deployment_name=new_container_name,
                    created_time = service['created_time'],
                    last_accessed_time = timezone.now(),
                    service_port = service['port'],
                    token = token,
                    pod_name = pod_name,

                )
                print('debug 8.2 ')
            else:
                print('debug 9.1 ')
                print('goTaskContainer: 数据库中存在容器记录，更新')
                container.student = student
                container.task = task
                container.deployment_name = new_container_name
                container.created_time = service['created_time']
                container.last_accessed_time = timezone.now()
                container.service_port = service['port']
                container.token = token
                container.pod_name = pod_name
                container.save()
                print('debug 9.2 ')
            url = 'http://172.20.216.103:'+str(port)+'/lab?token='+token
            return BaseView.successData({'url':url})
        except Exception as e:
            print(e)
            return BaseView.error(str(e))
    
    def getPythonImages(request):
        try:
            # 创建Docker客户端
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            nums = int(params.get('nums') )
            
            if nums==1:
                # 返回该课程的镜像
                pass
            else :
                # 返回所有镜像
                pass            
            docker_client = DockerClient.from_env()
            

            # 获取Python镜像列表
            python_images = docker_client.images.list(filters={'label': 'python'})

            # 格式化镜像信息，只保留需要的字段
            image_info = []
            for image in python_images:
                image_info.append({
                    'id': image.id,
                    'tag': image.tags[0],
                    'labels': image.labels,
                    'created': str(image.attrs['Created']),
                   'size': str(image.attrs['Size'])
                })

            # 返回镜像信息给前端
            return BaseView.successData(image_info)
        except Exception as e:
            # 处理异常情况
            return BaseView.error({'error': str(e)})
        
    def getContainers(request):
        try:
            # 创建Docker客户端
            docker_client = DockerClient.from_env()

            # 获取当前运行的容器列表
            containers = docker_client.containers.list()

            # 格式化容器信息，只保留需要的字段
            container_info = []
            for container in containers:
                container_info.append({
                    'id': container.id,
                    'name': container.name,
                    'status': container.status,
                    'ports': container.ports
                    # 可以根据需要添加更多的字段
                })

            # 返回容器信息给前端
            return BaseView.successData(container_info)
        except Exception as e:
            # 处理异常情况
            return BaseView.error({'error': str(e)})
    def get_cluster_overview(request):
        # 加载 kubeconfig 文件，如果没有指定，则使用默认的 kubeconfig 文件
        k8sManager =KubernetesManager()
        
        # 创建 CoreV1Api 的实例，用于与集群通信
        v1 = k8sManager.v1

        # 获取集群节点数量
        nodes = v1.list_node().items
        node_count = len(nodes)

        # 获取命名空间数量
        namespaces = v1.list_namespace().items
        namespace_count = len(namespaces)

        # 获取所有 Pod 的数量
        pods = v1.list_pod_for_all_namespaces().items
        pod_count = len(pods)

        # 获取所有 Service 的数量
        services = v1.list_service_for_all_namespaces().items
        service_count = len(services)

        # 获取所有 PersistentVolume 的数量
        pv = v1.list_persistent_volume().items
        pv_count = len(pv)

        # 获取所有事件的数量
        events = v1.list_event_for_all_namespaces().items
        event_count = len(events)

        return BaseView.successData(
           { "node_count": node_count,
            "namespace_count": namespace_count,
            "pod_count": pod_count,
            "service_count": service_count,
            "pv_count": pv_count,
            "event_count": event_count})
        
    def get_all_namespace(request):
        # 加载 kubeconfig 文件，如果没有指定，则使用默认的 kubeconfig 文件
        k8sManager =KubernetesManager()
        v1 = k8sManager.v1

        # 获取所有命名空间
        namespaces = v1.list_namespace().items

        ns_list = []
        for ns in namespaces:
            ns_list.append(ns.metadata.name)
        return BaseView.successData(ns_list)
    def get_pods(request):
        params=getParam(request)
        namespace = params.get('namespace')
        keyword = params.get('keyword')
        # 加载 kubeconfig 文件，如果没有指定，则使用默认的 kubeconfig 文件
        k8sManager =KubernetesManager()
        v1 = k8sManager.v1
        try:
            if namespace == '':
                # 获取所有命名空间的 Pod 列表
                pod_list = v1.list_pod_for_all_namespaces(watch=False)
            elif namespace and namespace!='':
                # 获取指定命名空间的 Pod 列表
                pod_list = v1.list_namespaced_pod(namespace)
            else:
                # 默认情况下，获取 'default' 命名空间的 Pod 列表
                pod_list = v1.list_namespaced_pod('default')
        except Exception as e:
            return BaseView.warn("namespace = "+namespace)
        # 提取必要信息并组织成字典列表
        necessary_info = []
        for pod in pod_list.items:
            pod_info = {
                'namespace': str(pod.metadata.namespace),
                'name': str(pod.metadata.name),
                'ip': str(pod.status.pod_ip),
                'status': str(pod.status.phase),
                # 'containers': [{
                #     'name': str(container.name),
                #     'image': str(container.image),
                #     'status': str(container.state)
                # } for container in pod.status.container_statuses],
                # 'labels': str(pod.metadata.labels),
                # 'annotations': str(pod.metadata.annotations),
                'create_time': pod.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                'update_time': pod.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S')
            }
            if keyword==None or keyword=='' or (keyword!='' and keyword in str(pod_info))  :
                necessary_info.append(pod_info)
        # 返回获取到的 Pod 列表
        return BaseView.successData(necessary_info)


    def get_pod_detail(request):
        params=getParam(request)
        namespace = params.get('namespace')
        pod_name = params.get('podName')
        # 加载 kubeconfig 文件，如果没有指定，则使用默认的 kubeconfig 文件
        k8sManager =KubernetesManager()
        v1 = k8sManager.v1

        # 获取指定命名空间的 Pod 列表
        pod_list = v1.list_namespaced_pod(namespace)
        
        # 提取必要信息并组织成字典列表
        necessary_info = []
        for pod in pod_list.items:
            if pod.metadata.name == pod_name:
                pod_info = {
                    'namespace': str(pod.metadata.namespace),
                    'name': str(pod.metadata.name),
                    'ip': str(pod.status.pod_ip),
                    'status': str(pod.status.phase),
                    'containers': [{
                        'name': str(container.name),
                        'image': str(container.image),
                        'status': str(container.state)
                    } for container in pod.status.container_statuses],
                    'labels': str(pod.metadata.labels),
                    'annotations': str(pod.metadata.annotations),
                    'create_time': pod.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                    'update_time': pod.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S')
                }
                return BaseView.successData(pod_info)

        # 返回获取到的 Pod 列表
        return BaseView.successData('None')
    
    def get_cluster_info(request):
        # 加载 kubeconfig 文件，如果没有指定，则使用默认的 kubeconfig 文件
        k8sManager =KubernetesManager()
        v1 = k8sManager.v1
        # 获取集群节点信息
        nodes = v1.list_node().items
        cluster_info = []

        # 打印节点信息
        for node in nodes:
            cluster_info.append({
                'name': node.metadata.name,# 节点名称
                'namespace': node.metadata.namespace,# 节点所在命名空间
                'createTime': str(node.metadata.creation_timestamp), # 节点创建时间
                'labels': node.metadata.labels,# 节点标签
                'ip': node.status.addresses[0].address, # 节点ip
                'allocatable': node.status.allocatable, # 可分配资源大小
                'capacity': node.status.capacity,# 总资源容量
                'pod_cidr': node.spec.pod_cidr, # 网络接口
                'conditions': str(node.status.conditions),  # 节点的状态条件
                'taints': str(node.spec.taints),  # 节点的污点信息
                'unschedulable': str(node.spec.unschedulable),  # 节点是否可调度
                'architecture': str(node.status.node_info.architecture),  # 节点的架构信息
                'kernel_version': str(node.status.node_info.kernel_version),  # 节点的内核版本
                'kubelet_version': str(node.status.node_info.kubelet_version),  # 节点的 kubelet 版本
                'os_image': str(node.status.node_info.os_image),  # 节点的操作系统镜像
                'container_runtime_version': str(node.status.node_info.container_runtime_version),  # 节点的容器运行时版本
                
                })
            # print(node.status.images)
        return BaseView.successData(cluster_info)
    
    def create_namespace(request):
        params=getParam(request)
        namespace_name = params.get('namespace')

        # 加载 Kubernetes 配置文件
        k8sManager =KubernetesManager()
        v1 = k8sManager.v1

        # 构建命名空间对象
        body = client.V1Namespace(metadata=client.V1ObjectMeta(name=namespace_name))

        try:
            # 调用 Kubernetes API 创建命名空间
            v1.create_namespace(body=body)
            print("命名空间 {} 创建成功！".format(namespace_name))
        except Exception as e:
            print("创建命名空间时出现错误：", e)
            
class CourseView(BaseView):
    def post(self, request, module, *args, **kwargs):
        
        
        # 课程
        if module == 'joinCourse':
            return CourseView.joinCourse(request)
        elif module == 'exitCourse':
            return CourseView.exitCourse(request)
        elif module == 'enterCourse':
            return CourseView.enterCourse(request)
        elif module == 'createCourse':
            return CourseView.createCourse(request)
        elif module == 'changeCourseStatus':
            return CourseView.changeCourseStatus(request)
        elif module == 'deleteCourse':
            return CourseView.deleteCourse(request)

        
        elif module == 'getMyCourseList':
            return CourseView.getMyCourseList(request)
        elif module == 'changeCourseEndTime':
            return CourseView.changeCourseEndTime(request)
        elif module == 'getCourseStudents':
            return CourseView.getCourseStudents(request)

        
        elif module == 'editCourse':
            return CourseView.editCourse(request)
        elif module == 'sendDoTaskEmail':
            return CourseView.sendDoTaskEmail(request)
        elif module == 'getTaskScore':
            return CourseView.getTaskScore(request)
        elif module == 'getCourseTaskWeights':
            return CourseView.getCourseTaskWeights(request)
        
        elif module == 'setCourseTaskWeights':
            return CourseView.setCourseTaskWeights(request)
        
        # 查询名字
        elif module =='searchCourseNames':
            return CourseView.searchCourseNames(request)
        elif module == 'searchClassNames':
            return CourseView.searchClassNames(request)
        

        # 老师


        elif module == 'getTeaCourses':
            return CourseView.getTeaCourses(request)

        
        # 作业

        elif module == 'getTaskAssignments':
            return CourseView.getTaskAssignments(request)
        elif module == 'getStudentTaskList':
            return CourseView.getStudentTaskList(request)
        elif module == 'setTaskScore':
            return CourseView.setTaskScore(request)
        elif module == 'deleteTask':
            return CourseView.deleteTask(request)
        elif module == 'getTaskOverview':
            return CourseView.getTaskOverview(request)

      
        # 论坛
        elif module == 'getCourseForumMessage':
            return CourseView.getCourseForumMessage(request)
        elif module == 'sendLikeMessage':
            return CourseView.sendLikeMessage(request)
        elif module == 'commitCourseForumMessage':
            return CourseView.commitCourseForumMessage(request)
        elif module == 'deleteCourseForumMessage':
            return CourseView.deleteCourseForumMessage(request)
        elif module =='sendReadAllMessage':
            return CourseView.sendReadAllMessage(request)
        
        
    def sendReadAllMessage(request):    
        try:
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            # 根据course_id查找课程
            courseEnrollment = models.Course2UserEnrollment.objects.get(course_id=course_id, user_id=user_id)
            courseEnrollment.unread_message_count = 0
            courseEnrollment.save()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def deleteCourseForumMessage(request):
        try:
            params = getParam(request)
            course_id = params.get('course_id')
            message_id = params.get('message_id')
            # 根据course_id查找课程
            course = models.Course.objects.get(course_id=course_id)
            message = models.ForumMessage.objects.get(id=message_id)
            message.delete()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
        
    
        
    def setCourseTaskWeights(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            homework_weight = params.get('homework_weight')
            experiment_weight = params.get('experiment_weight')
            exam_weight = params.get('exam_weight')
            # 根据course_id查找课程
            course = models.Course.objects.get(course_id=course_id)
            course.homework_weight = homework_weight
            course.experiment_weight = experiment_weight
            course.exam_weight = exam_weight
            course.save()
            return BaseView.success()
        
        except Exception as e:
            return BaseView.error(str(e))
        
    
    def getCourseTaskWeights(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            # 根据course_id查找课程
            course = models.Course.objects.get(course_id=course_id)

            task_weight_list = []
            task_weight_list.append({'name':'作业', 'weight': course.homework_weight})
            task_weight_list.append({'name':'实验', 'weight': course.experiment_weight})
            task_weight_list.append({'name':'考试', 'weight': course.exam_weight})
                
            return BaseView.successData(task_weight_list)
        except Exception as e:
            return BaseView.error(str(e))
        
    
    def commitCourseForumMessage(request):
        try :
            params = getParam(request)
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            course_id = params.get('course_id')
            content = params.get('message')
            course = models.Course.objects.get(course_id=course_id)
            
            enrollments = models.Course2UserEnrollment.objects.filter(course_id=course_id)
            for enrollment in enrollments:
                if enrollment.user_id!= user_id:
                    enrollment.unread_message_count += 1
                    enrollment.save()
            
            message = None
            if is_teacher == 'true' or is_teacher == True:
                teacher = models.Teacher.objects.get(user_id=user_id)
                message = course.forum_messages.create(sender_type='teacher', content=content, teacher=teacher)
            else:
                student = models.Student.objects.get(user_id=user_id)
                message = course.forum_messages.create(sender_type='student', content=content, student=student )
            
            
            return BaseView.successData({
                    "id": message.id,
                    "text": message.content,
                    "sender": {
                        "id": message.student.user_id if message.sender_type=="student" else message.teacher.user_id,
                        "name": message.student.name if message.sender_type=="student" else message.teacher.name,
                        "avatar": "https://example.com/avatar.jpg" # 或者相对路径，取决于实际存储位置
                    },
                    "timestamp": message.created_at.strftime('%Y-%m-%dT%H:%M:%SZ'), # ISO 8601格式的时间戳
                    "likesCount": 0,
                    "likedByCurrentUser": False # 可选，若已知当前用户是否点赞，方便前端直接显示状态
                    })
        except Exception as e:
            return BaseView.error(str(e))
        
        
        
    def sendLikeMessage(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            message_id = params.get('message_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            target_likedByCurrentUser = params.get('target_likedByCurrentUser')
            # 根据course_id查找课程
            course = models.Course.objects.get(course_id=course_id)
            message = models.ForumMessage.objects.get(id=message_id) 
            user_likes_ids = list(set(models.ForumMessageLike.objects.filter( user_id=user_id).values_list('message_id', flat=True)))
            d_count = -1
            if target_likedByCurrentUser == True or target_likedByCurrentUser == 'true':
                d_count = 1
                if message_id in user_likes_ids:
                    return BaseView.success()           
            if is_teacher == 'true' or is_teacher == True:    
                message.teacher_like_count += d_count
            else:
                message.student_like_count += d_count          
            message.save()
            if d_count==1:            
                models.ForumMessageLike.objects.create(message=message, user_id=user_id)
            else:
                models.ForumMessageLike.objects.filter(message=message, user_id=user_id).delete()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
        
            
    def getCourseForumMessage(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            # 根据course_id查找课程
            course = models.Course.objects.get(course_id=course_id)
            forum_messages = course.forum_messages.all()
            message_list = []
            
            user_likes_ids = list(set(models.ForumMessageLike.objects.filter( user_id=user_id).values_list('message_id', flat=True)))

            for message in forum_messages:
                fileview = FileView()
                user_id = message.student.user_id if message.sender_type=="student" else message.teacher.user_id
                avatar_url = fileview.getAvatarUrl(user_id )
                message_list.append({
                    "id": message.id,
                    "text": message.content,
                    "sender": {
                        "id": user_id,
                        "name": message.student.name if message.sender_type=="student" else message.teacher.name,
                        # "avatar": 'http://localhost:8000/media/avatars/avatar_default.png' # 或者相对路径，取决于实际存储位置
                        "avatar": avatar_url,
                    },
                    "timestamp": message.created_at.strftime('%Y-%m-%dT%H:%M:%SZ'), # ISO 8601格式的时间戳
                    "likesCount": message.student_like_count + message.teacher_like_count,
                    "likedByCurrentUser": message.id in user_likes_ids # 可选，若已知当前用户是否点赞，方便前端直接显示状态
                    },)
            return BaseView.successData(message_list)
        except Exception as e:
            return BaseView.error(str(e))
        
    
    def getTeaCourses(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id = params.get('user_id')
            # 根据tea_id查找课程
            courses = models.Course.objects.filter(creator_id=user_id)
            course_list = []
            for course in courses:
                course_list.append(course.name)
            return BaseView.successData(course_list)
        except Exception as e:
            return BaseView.error(str(e))
    
    def getTaskScore(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            # 根据task_id和stu_id查找task_submission
            taskScore = models.TaskScore.objects.filter(task_id=task_id, student_id=user_id).first()
            if taskScore:
                if taskScore.score_published:
                    return BaseView.successData(taskScore.score)

            return BaseView.successData('暂无成绩')

        except Exception as e:
            return BaseView.error(str(e))
        
    def sendDoTaskEmail(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            emailRange   = params.get('range')
            
            
            # 发送邮件
            course = models.Course.objects.get(course_id=course_id)
            course_name = course.name
            stu_ids = models.Course2UserEnrollment.objects.filter(course_id=course_id, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)
            tasks = course.tasks.all()
            info_lists = []
            
            # task_names = [task.name for task in tasks]
            if emailRange == 'homework':
                tasks = tasks.filter(task_type='作业')
            elif emailRange == 'experiment':
                tasks = tasks.filter(task_type='实验')
            elif emailRange == 'exam':
                tasks = tasks.filter(task_type='考试')
            elif emailRange == 'current':
                tasks = tasks.filter(task_id=task_id)
            
            
            # if emailRange == 'all':
            info_lists = [
                {
                    'user_id': student.user_id,
                    'name': student.name,
                    'email': student.email,
                    'task_name_list': [task.name for task in tasks],
                }for student in students
            ]
            for task in tasks:
                task_name = task.name
                task_submissions = task.submissions.all()
                submitted_stu_ids = task_submissions.values_list('student_id', flat=True).distinct()
                for info in info_lists:
                    if info['user_id'] in submitted_stu_ids:
                        info['task_name_list'].remove(task_name)
            
            # elif emailRange == 'current':
            #     task = models.Task.objects.get(task_id=task_id)
            #     info_lists = [
            #         {
            #             'user_id': student.user_id,
            #             'name': student.name,
            #             'email': student.email,
            #             'task_name_list': [task.name],
            #         }for student in students
            #     ]
            #     task_submissions = task.submissions.all()
            #     submitted_stu_ids = task_submissions.values_list('student_id', flat=True).distinct()
            #     for info in info_lists:
            #         if info['user_id'] in submitted_stu_ids:
            #             info['task_name_list'].remove(task.name)
                        
            for info in info_lists:
                if len(info['task_name_list']) == 0:
                    continue
                EmailUtil.send_do_task_email(info['email'],info['task_name_list'], course_name=course_name)
                
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    

        
    def editCourse(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id') # 课程id
            name = params.get('className') # 课程名称
            teachingCourseName = params.get('teachingCourseName') # 授课课程名称
            term = params.get('term') # 学期
            description = params.get('description') # 课程描述
            end_time = params.get('end_time') # 课程结束时间
            cover = params.get('cover') # 课程封面
            homework_weight = params.get('homework_weight') # 作业权重
            experiment_weight = params.get('experiment_weight') # 实验权重
            exam_weight = params.get('exam_weight') # 考试权重

            
            course = models.Course.objects.get(course_id=course_id)
            course.name = name
            course.teachingCourseName = teachingCourseName
            course.term = term
            course.description = description
            course.end_time = end_time
            course.homework_weight = homework_weight
            course.experiment_weight = experiment_weight
            course.exam_weight = exam_weight
            course.save()
     
            FileView.setCover(course=course, file=cover)
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
            
    
    def getTaskOverview(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            # 获取作业信息
            course = models.Course.objects.get(course_id=course_id)
            stu_ids = models.Course2UserEnrollment.objects.filter(course_id=course_id, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)
            stu_ids = [student.user_id for student in students]
            stu_ids = sorted(stu_ids)

            total_count = students.count()
            task = course.tasks.get(task_id=task_id)
            task_submittions = task.submissions.all()
            task_scores = models.TaskScore.objects.filter(task_id=task_id, student_id__in=stu_ids)
            # 组装数据
            submitted_stus = [{'user_id':submittion.student.user_id, 'name':submittion.student.name} for submittion in task_submittions]
            submitted_stus = sorted(submitted_stus, key=lambda x:stu_ids.index(x['user_id']))
            
            marked_stus = [{'user_id':task_score.student.user_id, 'name':task_score.student.name} for task_score in task_scores]
            marked_stus = sorted(marked_stus, key=lambda x:stu_ids.index(x['user_id']))
            # marked_stus = [{'user_id':submittion.student.user_id, 'name':submittion.student.name} for submittion in task_submittions if submittion.status=='已批改']
            # 对submittions和stu_enrollments去重
            submitted_stus = [dict(t) for t in set([tuple(d.items()) for d in submitted_stus])]
            marked_stus = [dict(t) for t in set([tuple(d.items()) for d in marked_stus])]
            submit_count = len(submitted_stus)
            mark_count = len(marked_stus)
            # 将字典转换为元组，并去重
            submitted_stus_tuples = [tuple(d.items()) for d in submitted_stus]
            marked_stus_tuples = [tuple(d.items()) for d in marked_stus]

            unsubmitted_stus = [{'user_id':student.user_id, 'name':student.name} for student in students if tuple({'user_id': student.user_id, 'name': student.name}.items()) not in submitted_stus_tuples]
            unmarked_stus = [{'user_id':student.user_id, 'name':student.name} for student in students if tuple({'user_id': student.user_id, 'name': student.name}.items()) not in marked_stus_tuples]
            result = [
                {
                    'value': int(submit_count/total_count*100) if total_count!=0 else 0,
                    'name': '已提交',
                    'stu_list':submitted_stus,
                    'stu_list2':unsubmitted_stus,
                },
                {
                    'value': int(mark_count/total_count*100)if total_count!=0 else 0,
                    'name': '已批改',
                    'stu_list':marked_stus,
                    'stu_list2':unmarked_stus,
                }
            ]
            return BaseView.successData(result)
        except Exception as e:
            return BaseView.error(str(e))
    
    
    def deleteTask(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            course_id = params.get('course_id')
            task = models.Task.objects.get(task_id=task_id)
            if task.imported_from_task_id!=None :
                course_name = models.Course2Task.objects.get(task_id=task.imported_from_task_id).course.name
                return BaseView.warn(f'该任务为导入任务，不可删除，请在父课程【{course_name}】中删除')
            task_type = task.task_type
            if not (is_teacher == 'true' or is_teacher == True):
                return BaseView.warn('无删除权限')
            course = models.Course.objects.get(course_id=course_id)
            if task_type == 'homework' or task_type == '作业' :
                course.homework_count -=1
            elif task_type == 'experiment' or task_type == '实验':
                course.experiment_count -=1
            elif task_type == 'exam' or task_type == '考试':
                course.exam_count -=1
            course.save()
            task = models.Task.objects.get(task_id=task_id)
            task.delete()
            for task in models.Task.objects.all():
                if task.imported_from_task_id == task_id:
                    task.delete()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
        
    def setTaskScore(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            stu_id = params.get('stu_id')
            score = params.get('score')
            user_id = params.get('user_id')
            teacher = models.Teacher.objects.get(user_id=user_id)
            teacher_name = teacher.name
            
            # 根据task_id和stu_id查找task_submission
            # task_submissions = task.submissions.filter(student_id=stu_id)
            task = models.Task.objects.get(task_id=task_id)
            submittions = task.submissions.filter(student_id=stu_id)
            max_score = task.score
            for submittion in submittions:
                file = submittion.submit_file.name
                if file.endswith('.pdf'):
                    from .utils.watermark import Watermark
                    watermark = Watermark()
                    marked_file = watermark.make_score_watermark(file, teacher_name, score, max_score)
                    submittions.update(marked_file=marked_file)
                    
            task_score = models.TaskScore.objects.filter(task_id=task_id, student_id=stu_id)
            
            if task_score.exists():
                task_score.update(score=score, score_published=False)
            else:
                models.TaskScore.objects.create(task_id=task_id, student_id=stu_id, score=score, score_published=False)
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    

    
    def getStudentTaskList(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = str(params.get('course_id'))
            task_id = str(params.get('task_id'))
            # 获取学生列表
            course = models.Course.objects.get(course_id=course_id)
            task = course.tasks.get(task_id=task_id)
            stu_ids = models.Course2UserEnrollment.objects.filter(course_id=course_id, role='student').values_list('user_id', flat=True)
            # stu_ids = [student.user_id for student in students]
            students = models.Student.objects.filter(user_id__in=stu_ids)
            # 获取作业提交列表
            task_submissions = task.submissions.all()
            task_scores = models.TaskScore.objects.filter(task_id=task_id, student_id__in=stu_ids)

            result = [
                {
                    'user_id':student.user_id,
                    'name':student.name,
                    'score':0,
                    'status':'未提交',
                    'max_score':task.score,
                    'file_list':[],
                }
                for student in students
            ]
            result = sorted(result, key=lambda x:x['user_id'])
            for res in result:
                task_submission = task_submissions.filter(student_id=res['user_id'])
                task_score = task_scores.filter(student_id=res['user_id'])
                if task_submission.exists():
                    res['status']='已提交，待批改'
                    # res['score']=task_submission.first().score
                if task_score.exists():
                    if task_score.first().score_published:
                        res['status']='已发布'
                    else:
                        res['status']='待发布'
                    res['score']=task_score.first().score

                
            for task_submission in task_submissions:
                # 从result中找到对应的学生
                for student in result:
                    if student['user_id'] == task_submission.student.user_id:
                        print("user_id= ",task_submission.student.user_id, ", name= ",task_submission.student.name)
                        # print("score= ",task_submission.score, ", status= ",task_submission.status, ", max_score= ",task.score)
                        index = result.index(student)
                        # result[index]['score'] = task_submission.score
                        # result[index]['status'] = task_submission.status
                        result[index]['max_score'] = task.score
                        result[index]['file_list'].append(os.path.basename(task_submission.submit_file.name))
                        break
            # scores = 
            return BaseView.successData(result)
        except Exception as e:
            return BaseView.error(str(e))

    def getTaskAssignments(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            task_id = params.get('task_id')
            print('task_id = ',task_id)
            print('course_id = ',course_id)
            course = models.Course.objects.get(course_id=course_id)
            enrollments = models.Course2UserEnrollment.objects.filter(course_id=course_id, role='student')
            stu_ids = [enroll.user_id for enroll in enrollments]
            
            total_size = len(stu_ids)
            # 升序排序
            # stu_ids = sorted(stu_ids)[start_index:end_index]
            stu_ids = sorted(stu_ids)
            # 获取学生列表
            students = models.Student.objects.filter(user_id__in=stu_ids)

            # 获取作业提交列表
            task = course.tasks.get(task_id=task_id)
            
            result = [{
                'user_id':student.user_id,
                'name':student.name,
                'task_name':task.name,
                'submitted':"未提交",
                'score':0,
                'max_score':task.score,
                'status':'待批改'
            } for student in students]
            # 按学号从小到大排序
            result = sorted(result, key=lambda x:x['user_id'])

                
            studentSubmits = task.submissions.all()
            task_scores = models.TaskScore.objects.filter(task_id=task_id, student_id__in=stu_ids)

            for res in result:
                task_score = task_scores.filter(student_id=res['user_id'])
                task_submit = studentSubmits.filter(student_id=res['user_id'])
                if task_submit.exists():
                    res['submitted']='已提交'
                if task_score.exists():
                    if task_score.first().score_published:
                        res['status']='已发布'
                    else:
                        res['status']='待发布'
                    res['score']=task_score.first().score

            return BaseView.successData({'data':result, 'total_size':total_size})
        except Exception as e:
            return BaseView.error(str(e))
            
    
    def changeCourseEndTime(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            end_time = params.get('end_time')
            # 更新课程结束时间
            course = models.Course.objects.get(course_id=course_id)
            course.end_time = end_time
            if end_time == None or end_time == '':
                course.status = 'ongoing'
            else:
                offset = getTimeOffset(course.start_time, end_time)
                if offset < 0:
                    course.status = 'pending'
                elif offset == 0:
                    course.status = 'ongoing'
                else:
                    course.status = 'finished'
            course.updated_at = timezone.now()
            course.save()
            return BaseView.success()

        except Exception as e:
            return BaseView.error(str(e))
    
    
    def getMyCourseList(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id = params['user_id']
            is_teacher = params['is_teacher']
            page = int(params.get('page', 1))
            pageSize = int (params.get('pageSize', 10))
            course_list = []
            if  is_teacher == True or is_teacher == 'true':
                teacher = models.Teacher.objects.get(user_id=user_id)
                courses = models.Course.objects.filter(creator=teacher)
            else:
                student = models.Student.objects.get(user_id=user_id)
                stu_enrollments = models.Course2UserEnrollment.objects.filter(user_id=student.user_id)
                course_ids = [enrollment.course.course_id for enrollment in stu_enrollments]
                courses = models.Course.objects.filter(course_id__in=course_ids)
                # courses = models.Course.objects.filter(students=student)
            
            # 分页逻辑
            start_index = (page - 1) * pageSize
            end_index = start_index + pageSize
            paginated_courses = courses[start_index:end_index]
            
            total = len(courses)
            # 获取用户课程列表

            for course in paginated_courses:
                homework_count = course.homework_count
                exam_count = course.exam_count
                experiment_count = course.experiment_count
                cover = FileView.getShinkedCover(course,max_width=300,max_height=300) # 获取压缩后的课程封面
                if course.share_files:
                    father_course = models.Course.objects.get(course_id=course.imported_from_course_id)
                    experiment_count = father_course.experiment_count
                    exam_count = father_course.exam_count
                    homework_count = father_course.homework_count
                    
                course_list.append({
                    'id': course.course_id,
                    'title': course.name,
                    'image': cover,
                    'teacher':course.creator.name,
                    'term': course.term,
                    'time':  ustime2cntime(course.created_at),
                    'status': course.status,
                    'homework_count': homework_count,
                    'exam_count': exam_count,
                    'experiment_count': experiment_count,
                    
                })
            pager = {
                "page":page,
                "pageSize":pageSize,
                "total":total,
            }
            return BaseView.successData({'list':course_list, "pager":pager})
        except Exception as e:
            return BaseView.error(str(e))
    
   
    def searchClassNames(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id= params.get('user_id')
            # 获取课程班级列表
            courses = models.Course.objects.filter(creator_id=user_id)
            class_list = []
            for course in courses:
                if course.imported_from_course_id==None or course.imported_from_course_id=='':
                    class_list.append(
                        course.name,
                    )
            return BaseView.successData(class_list)
        except Exception as e:
            return BaseView.error(str(e))
    
    def searchCourseNames(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id = params.get('user_id')
            # 获取课程班级列表
            courses = models.Course.objects.filter(creator_id=user_id)
            course_list = []
            for course_ in courses:
                course_list.append(
                     course_.teachingCourseName,
                )
            return BaseView.successData(list(set(course_list)))
        except Exception as e:
            return BaseView.error(str(e))
    
    def getCourseStudents(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            course_id = params.get('course_id')
            page = int(params.get('page', 1))
            pageSize = int (params.get('pageSize', 10))
            query = params.get('query')
    
            # 获取课程学生列表
            course = models.Course.objects.get(course_id=course_id)
            # return BaseView.successData(course)
            if is_teacher == True or is_teacher == 'true':
                pass
            else:
                pass
            tasks = course.tasks.all()
            stu_ids =  models.Course2UserEnrollment.objects.filter(course=course, role='student').values_list('user_id', flat=True)
            total = len(stu_ids)
            # 学号从小到大排序
            stu_ids = sorted(stu_ids)[pageSize*(page-1):pageSize*page]
            result = []
            # 根据stu_ids获取提交记录
            # task_submissions = models.TaskSubmission.objects.filter(student_id__in=stu_ids)
            title = [['id','学号'], 
                     ['name','姓名'], 
                    #  ['gender','性别'], 
                     ['school','学校'], 
                     ['college','学院'], 
                     ['major','专业'], 
                     ['email','邮箱'], 
                    #  ['phone','手机号'],
                     ]
            for user_id in stu_ids:
                # task_scores = models.Task.objects.
                student = models.Student.objects.get(user_id=user_id)
                # submit = task_submissions.filter(student_id=user_id)
                stu_data = {
                    'id':student.user_id,
                    'name':student.name,
                    # 'gender':student.gender,
                    'school':student.school,
                    'college':student.college,
                    'major':student.major,
                    'email':student.email,
                    # 'phone':student.phone_number,
                }
                for task in tasks :
                    stu_data[task.name] = 0
                result.append(stu_data)
            for task in tasks:
                title.append([task.name,task.name])
                scores = models.TaskScore.objects.filter(task=task)
                for stu_data in result:
                    if scores.filter(student_id=stu_data['id']).exists():
                        stu_data[task.name] = scores.get(student_id=stu_data['id']).score
                
            return BaseView.successData({"data":result,"total_size":total, 'title':title})
        except Exception as e:
            return BaseView.error(str(e))


    
    def joinCourse(request, stu_info=None):
        try:
            # 获取参数
            if stu_info == None:
                params = getParam(request)
                course_id = params.get('course_id')
                user_id = params.get('user_id')
                is_teacher = params.get('is_teacher')
            else:
                course_id = stu_info['course_id']
                user_id = stu_info['user_id']
                is_teacher = stu_info['is_teacher']
            # 加入课程
            course = models.Course.objects.get(course_id=course_id)
            if course.status != 'ongoing':
                return BaseView.warn('不能加入该课程')
            stu_ids = models.Course2UserEnrollment.objects.filter(course=course, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)


            if is_teacher == True or is_teacher == 'true':
                res = TeacherView.checkSetAllInfo(user_id)
                if res != True:
                    return BaseView.warn('请先完善个人信息')
                teacher = models.Teacher.objects.get(user_id=user_id)
                return BaseView.warn('暂未开通教师加入班级的功能')
            else:
                res=  StudentView.checkSetAllInfo(user_id)
                #  如何是教师导入学生，那么不需要判断是否填完整信息。
                if stu_info == None:
                    if res != True:
                        return BaseView.warn('请先完善个人信息')
                student = models.Student.objects.get(user_id=user_id)
                if student in students:
                    return BaseView.warn('已经在课程里面了')
                messages_counts = course.forum_messages.count()
                models.Course2UserEnrollment.objects.create(course=course, user_id=student.user_id, role='student',unread_message_count=messages_counts)
            course.save()

            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def exitCourse(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            # 退出课程
            course = models.Course.objects.get(course_id=course_id)
            stu_ids = models.Course2UserEnrollment.objects.filter(course=course, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)

            if is_teacher == True or is_teacher == 'true':
                teacher = models.Teacher.objects.get(user_id=user_id)
                return BaseView.warn('老师不能退出课程')
            else:
                student = models.Student.objects.get(user_id=user_id)
                # 查找学生是否已经在课程里面
                if student not in students:
                    return BaseView.warn('不在课程里面')
                student = models.Course2UserEnrollment.objects.get(course=course, user_id=student.user_id)
                if student :
                    student.delete()
                # containers = models.Container.objects.filter(courseEnrollment==courseEnrollment,student=student)
                
                
                # # k8sManager = KubernetesManager()
                # # k8sManager.delete_stu_all_pod('homework-'+task_id+'-'+user_id)
                # if containers.exists():
                #     for container in containers:
                #         container.delete()
                        
                        
            course.save()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def enterCourse(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            is_teacher = params.get('is_teacher')
            user_id = params.get('user_id')
            
            course = models.Course.objects.get(course_id=course_id)
            stu_ids = models.Course2UserEnrollment.objects.filter(course=course, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)
            if is_teacher == True or is_teacher == 'true':
                teacher = models.Teacher.objects.get(user_id=user_id)
            # 获取课程详情
            homework_weight = course.homework_weight
            exam_weight = course.exam_weight
            experiment_weight = course.experiment_weight
            if course.share_files:
                father_course = models.Course.objects.get(course_id=course.imported_from_course_id)
                homework_weight = father_course.homework_weight
                exam_weight = father_course.exam_weight
                experiment_weight = father_course.experiment_weight
            course_detail = {
                'course_id': course.course_id,
                'teachingCourseName':course.teachingCourseName,
                'title': course.name,
                'cover':FileView.getShinkedCover(course,max_width=600, max_height=600),
                'description': course.description,
                'term': course.term,
                'status':course.status,
                'create_time': ustime2cntime(course.created_at),
                'update_time': ustime2cntime(course.updated_at),
                'start_time': ustime2cntime(course.start_time),
                'end_time': ustime2cntime(course.end_time) if course.end_time else "None",
                'stu_counts':students.count(),
                'homework_weight':homework_weight,
                'experiment_weight':experiment_weight,
                'exam_weight':exam_weight,
                'unread_message_count':models.Course2UserEnrollment.objects.get(course=course, user_id=user_id).unread_message_count,
                # 'create_time': str(course.created_at),
                # 'update_time': str(course.updated_at),
                # 'start_time': str(course.start_time),
                # 'end_time': str(course.end_time),
                
                # 'teacher': teacher.name,
                # 'teacher_id': teacher.user_id,
                # 'teacher_email': teacher.email,
                # 'teacher_school': teacher.school,
                # 'teacher_college': teacher.college,
                # 'teacher_phone': teacher.phone_number,
            }
            return BaseView.successData(course_detail)
        except Exception as e:
            return BaseView.error(str(e))
    
    def getNextCourseId(request):
        models.Course.objects.all().order_by('-course_id')[0].id + 1
        
    def createCourse(request):  
        try:
            # 获取参数
            params = getParam(request)
            course_cover = params.get('img')    # 课程封面
            className = params.get('className')    # 班课名称
            courseName = params.get('courseName')    # 课程名称
            term = params.get('term')    # 学期
            user_id = params.get('user_id')    # 老师
            import_course = params.get('import_course')    # 是否导入课程
            pre_course_name = params.get('pre_course_name')    # 前置课程
            share_files = params.get('share_files')    # 共享文件
            
            res = TeacherView.checkSetAllInfo(user_id)
            if res != True:
                return BaseView.warn('请先完善个人信息')

            teacher  = models.Teacher.objects.get(user_id=user_id)
            
            pre_course = models.Course.objects.filter(name=pre_course_name)
            for course in models.Course.objects.all():
                if course.name == className:
                    return BaseView.warn('班课名称已存在')
            if pre_course.exists():
                pre_course = pre_course.first()
            
                new_course = models.Course(share_files=share_files,
                                        name=className,
                                        teachingCourseName = courseName,
                                        term=term, 
                                        creator=teacher,
                                        imported_from_course_id =pre_course.course_id,
                                        homework_count=pre_course.homework_count,
                                        exam_count = pre_course.exam_count,
                                        experiment_count = pre_course.experiment_count,
                                        homework_weight=pre_course.homework_weight,
                                        exam_weight=pre_course.exam_weight,
                                        experiment_weight=pre_course.experiment_weight,
                                        )
            else:
                new_course = models.Course(share_files=share_files,
                        name=className,
                        teachingCourseName = courseName,
                        term=term, 
                        creator=teacher,
                        # imported_from_course_id =pre_course.course_id,
                        # homework_count=pre_course.homework_count,
                        # exam_count = pre_course.exam_count,
                        # experiment_count = pre_course.experiment_count,
                        # homework_weight=pre_course.homework_weight,
                        # exam_weight=pre_course.exam_weight,
                        # experiment_weight=pre_course.experiment_weight,
                        )
            new_course.save()
            
            FileView.setCover(course=new_course, file=course_cover)
            
            models.Course2UserEnrollment.objects.create(course=new_course, 
                                                        user_id=teacher.user_id, 
                                                        role='teacher',
                                                        
                                                        )
            if import_course == True or import_course == 'true':
                # 将所有作业、实验、考试都加入到这个新班级

                tasks = pre_course.tasks.all()
                for task in tasks:
                    new_task = models.Task.objects.create(name=task.name,
                                                          description=task.description,
                                                          task_type=task.task_type, 
                                                          start_time = task.start_time,
                                                          end_time = task.end_time,
                                                          teacher=teacher,
                                                          imported_from_task_id=task.task_id,
                                                          )
                    new_course.tasks.add(new_task)
                    if share_files == True or share_files == 'true':
                        # 共享文件，只需要复制文件的目录
                        pass
                    else:
                        # 复制文件到新班级
                        taskFiles = models.TaskFiles.objects.filter(task=task)
                        
                        for taskFile in taskFiles:
                            new_file_dir = getTaskTeachingSourceDir(new_course.course_id, new_task.task_id, new_task.task_type)
                            # print('new_file_dir = ', new_file_dir)
                            new_task = models.TaskFiles.objects.create(task=new_task, file_type=taskFile.file_type, file=os.path.join(new_file_dir, os.path.basename(taskFile.file.name).split('/')[-1]))
                            file_view = FileView()
                            file_view.copy_file(taskFile.file.name, new_task.file.name)

            
            return BaseView.success()

          
        except Exception as e:
            return BaseView.error(str(e))
    
    def changeCourseStatus(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            status = params.get('status')
            
            course = models.Course.objects.get(course_id=course_id)
            teacher = models.Teacher.objects.get(user_id=user_id)
            
            course.status = status
            course.save()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def deleteCourse(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            
            teacher = models.Teacher.objects.get(user_id=user_id)
            course = models.Course.objects.get(course_id=course_id)
            if course.creator == teacher:
                # 删除课程的封面
                FileView.deleteCover(course=course)
                # 老师上传的文件不能删。
                # models.TaskFiles.objects.filter(task__course=course).delete()
                models.Task.objects.filter(course=course).delete()
                models.Course2Task.objects.filter(course=course).delete()
                models.Course2UserEnrollment.objects.filter(course=course).delete()
                course.delete()
                
                return BaseView.success()
            else:
                return BaseView.warn('无权限')
        except Exception as e:
            return BaseView.error(str(e))

    
   
    

class TaskView(BaseView):
    def post(self, request, module, *args, **kwargs):
        # 作业
        # 教师学生公共操作
        if module == 'getTaskDetail':
            return TaskView.getTaskDetail(request)
        elif module == 'getMyTaskList':
            return TaskView.getMyTaskList(request)
        # 教师端
        elif module == 'createTask':
            return TaskView.createTask(request)
        elif module == 'updateTask':
            return TaskView.updateTask(request)
 
        elif module == 'setTaskFiles':
            return TaskView.setTaskFiles(request)
        elif module == 'setTaskFiles2':
            return TaskView.setTaskFiles2(request)
        elif module == 'getTaskFiles':
            return TaskView.getTaskFiles(request)
        elif module == 'deleteStuTaskFile':
            return TaskView.deleteStuTaskFile(request)
        elif module == 'handlePublishScore':
            return TaskView.handlePublishScore(request)
        elif module == 'deleteTeaTaskFile':
            return TaskView.deleteTeaTaskFile(request)
        # 学生端
        elif module == 'submitTask':
            return TaskView.submitTask(request)
        elif module == 'getSubmittedTaskFiles':
            return TaskView.getSubmittedTaskFiles(request)
        elif module == 'downloadTeachingSourceFile':
            return TaskView.downloadTeachingSourceFile(request)

    def get(self, request, module, *args, **kwargs):
        return BaseView.error('错误的请求方式')
    
    def handlePublishScore(request):
        try:
            # 获取参数  
            params = getParam(request)
            print(params)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            course = models.Course.objects.get(course_id=course_id)
            stu_ids = models.Course2UserEnrollment.objects.filter(course=course, role='student').values_list('user_id', flat=True)
            students = models.Student.objects.filter(user_id__in=stu_ids)
            task = models.Task.objects.get(task_id=task_id)
            task_scores = models.TaskScore.objects.filter(task_id=task_id)
            for student in students:
                task_score = task_scores.filter(student_id=student.user_id)
                if not task_score.exists():
                    return BaseView.warn('请批改所有学生的作业再发布成绩')
            for student in students:
                task_scores.filter(student_id=student.user_id).update(score_published=True)
            task.score_published = True
            task.save()
            return BaseView.success()
        except Exception as e:
            print(e)
            return BaseView.error(str(e))
           
    
    def downloadTeachingSourceFile(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            file_name = params.get('file_name')
            task_type = params.get('task_type')
            # 获取作业文件列表
            fileDir = getTaskTeachingSourceDir(course_id, task_id, task_type)
            file_path = fileDir+'/'+file_name
            # 获取file_path的文件，为了减少网络占用，直接返回一个blob链接
            # response = FileView.getBlobLink(file_path)
            # 下载作业文件
            # response = FileView.downloadFile(fileDir+'/'+file_name)
            return BaseView.successData(file_path)
        except Exception as e:
            return BaseView.error(str(e))
    

    
    def getSubmittedTaskFiles(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            user_id = params.get('user_id')
            # 获取作业文件列表
            task = models.Task.objects.get(task_id=task_id)
            submitions = task.submissions.filter(student_id=user_id)
            # 获取提交的文件的名字，名字存储在TaskSubmission的submit_file字段中
            file_list = []
            for submition in submitions:
                file_list.append(os.path.basename(submition.submit_file.name))
            return BaseView.successData(file_list)
            
        except Exception as e:
            return BaseView.error(str(e))
    

    
    def submitTask(request, backupFile=None):
        try:
            if backupFile==None:
                # 从request中获取参数
                params = getParam(request)
                task_id = params.get('task_id')
                course_id = params.get('course_id')
                user_id = params.get('user_id')
                file_name = params.get('file_name')
                file_content = params.get('file_content')
                task_type = params.get('task_type')
            else:
                # 从duplicate_student_file中获取参数
                task_id = backupFile['task_id']
                course_id = backupFile['course_id']
                user_id = backupFile['user_id']
                file_name = backupFile['file_name']
                task_type = backupFile['task_type']
                file_path = backupFile['file_path']
                file_type =  get_file_base64_prefix_type(file_path)
                # 使用mimetypes库结果可能是None，需要改进。现在手动写死了ipynb的类型。
                # 学生手动上传文件的时候，前端可以传过来类型信息，也就是if的第一种情况。可以在此基础上记录文件类型，避免使用mimetypes库。   
                print("get_file_base64_prefix_type: file_path = ", file_path, ", file_type = ", file_type)
                with open(file_path, 'rb') as f:
                    file_content = str(base64.b64encode(f.read()))
            # 保存作业文件
            file_dir = getTaskStuSubmitDir(course_id, task_id, user_id, task_type)
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
            if backupFile==None:
                file_path = file_dir+'/'+file_name
                temp = file_content.split(',')
                file_type=temp[0]
                with open(file_path, 'wb+')as destination:
                    file_content = base64.b64decode(temp[1])
                    # file_content = base64.b64decode(file_content)
                    destination.write(file_content)
            # 保存作业提交记录
            task = models.Task.objects.get(task_id=task_id)
            student = models.Student.objects.get(user_id=user_id)
            task_submission = models.TaskSubmission.objects.filter(task=task, student=student)
            # 判断是有有相同文件的提交记录,如果有，那么删除
            for submition in task_submission:
                if file_path == submition.submit_file.name:
                    submition.delete()
                    break
            submittion = models.TaskSubmission.objects.create(
                task=task,
                student=student,
                submitted_time=datetime.now(),
                submit_file=file_path,
                submitted = True,
                file_type=file_type,
            )
            models.Task2Submission.objects.create(
                task=task,
                submission=submittion,
            )
            return BaseView.success()
        except Exception as e:
            if backupFile!=None:
                return str(e)
            return BaseView.error(str(e))
    
    
    def deleteStuTaskFile(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            file_name = params.get('file_name')
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            task_type = params.get('task_type')
            # print("file_name = ", file_name)
            # 获取作业文件列表
            fileDir = getTaskStuSubmitDir(course_id, task_id,user_id, task_type)
            # print("删除学生文件：目录 = ",fileDir)
            # 删除作业文件
            # 如果文件的后缀匹配，那么删除文件
            if os.path.isfile(fileDir+'/'+file_name):
                os.remove(fileDir+'/'+file_name)
                # print("本地删除文件成功file deleted")
            # 同时删除数据库记录
            # print(fileDir+'/'+file_name)
            # task = models.Task.objects.get(task_id=task_id)
            # student = models.Student.objects.get(user_id=user_id)
            submissions = models.TaskSubmission.objects.filter(student_id=user_id)
            # submissions =models.TaskSubmission.objects.filter(student_id = user_id, task_id = task_id)
            counts  = submissions.count()    
            for submission in submissions:
                if os.path.basename(submission.submit_file.name) == file_name:
                    submission.delete()
                    # print("数据库删除记录成功")
                    break
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
                
    def deleteTeaTaskFile(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            file_name = params.get('file_name')
            task_type = params.get('task_type')
            # 获取作业文件列表
            fileDir = getTaskTeachingSourceDir(course_id, task_id, task_type)
            # 删除作业文件
            # 如果文件的后缀匹配，那么删除文件
            if os.path.isfile(fileDir+'/'+file_name):
                os.remove(fileDir+'/'+file_name)
            # 同时删除数据库记录
            task_files = models.TaskFiles.objects.filter(task_id=task_id)
            for task_file in task_files:
                if os.path.basename(task_file.file.name) == file_name:
                    task_file.delete()
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def getTaskFiles(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            task_type = params.get('task_type')
            
            
            course = models.Course.objects.get(course_id=course_id)
            task = models.Task.objects.get(task_id=task_id)
            

            if course.share_files:
                task_id = task.imported_from_task_id
            # 获取作业文件列表
            task_files = models.TaskFiles.objects.filter(task_id=task_id)
            file_list = []
            for task_file in task_files:
                file_list.append(
                   os.path.basename(task_file.file.name),
                )
            return BaseView.successData(file_list)
        except Exception as e:
            return BaseView.error(str(e))
    

    def setTaskFiles2(request):
        try:
            # 获取参数
            file   = request.FILES.get('file')
            print("request.FILES.keys() = ",request.FILES.keys())
            print("request.POST.keys() = ",request.POST.keys())
            course_id = request.POST.get('course_id')
            task_id = request.POST.get('task_id')
            task_type = request.POST.get('task_type')
            file_name = str(file)
            
            task = models.Task.objects.get(task_id=task_id)
            
            file_dir = getTaskTeachingSourceDir(course_id, task_id, task_type)
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
                
            file_path = file_dir+'/'+file_name
            file_type = ''
            with open(file_path, 'wb+')as destination:
                for chunk in file.chunks():
                    destination.write(chunk)
                # destination.write(file)
            os.chmod(file_path, 0o444) 
            existFiles = models.TaskFiles.objects.filter(task=task, file=file_path)
            if not existFiles.exists():
                models.TaskFiles.objects.create(
                    task=task,
                    file=file_path,
                    file_type='',
                    )
            return BaseView.success()
        except Exception as e:
            print(e)
            return BaseView.error(str(e))
    
    def setTaskFiles(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = params.get('task_id')
            course_id = params.get('course_id')
            file_name = params.get('file_name')
            file = params.get('file')
            task_type = params.get('task_type')
            
            task = models.Task.objects.get(task_id=task_id)
            
            file_dir = getTaskTeachingSourceDir(course_id, task_id, task_type)
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
                
            file_path = file_dir+'/'+file_name
            file_type = ''
            with open(file_path, 'wb+')as destination:
                temp = file.split(',')
                file = base64.b64decode(temp[1])
                file_type = temp[0]
                destination.write(file)
            os.chmod(file_path, 0o444) 
            models.TaskFiles.objects.create(
                task=task,
                file=file_path,
                file_type=file_type,
                )
            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))
    
    def getTaskDetail(request):
        try:
            # 获取参数
            params = getParam(request)
            task_id = str(params.get('task_id'))
            course_id = str(params.get('course_id'))
            is_teacher = params.get('is_teacher')
            user_id = str(params.get('user_id'))
            token = params.get('token')
            # 获取作业详情
            course = models.Course.objects.get(course_id=course_id)
            task = course.tasks.get(task_id=task_id)
            if not task:
                return BaseView.warn('作业不存在')
            # task = models.Task.objects.get(task_id=task_id)
            task_submission = None
            if is_teacher == True or is_teacher == 'true':
                pass
                # teacher = models.Teacher.objects.get(user_id=user_id)
            else:
                student = models.Student.objects.get(user_id=user_id)
                task_submission = models.TaskSubmission.objects.filter(student=student, task=task)
            # if task.course != course:
            #     return BaseView.error('课程与作业不匹配')
            if task_submission and task_submission.exists() and not(is_teacher == True or is_teacher == 'true'):
                submitted_time = ustime2cntime( task_submission.first().submitted_time)
            else:
                submitted_time = None

            homework_detail = {
                
                'course_id': course.course_id,
                'course_name': course.name,
                'task_id': task.task_id,
                'task_name': task.name,
                'task_type': task.task_type,
                'description': task.description,
                'tea_name': task.teacher.name,
                # 'user_id': task.teacher.user_id,
                # 'tea_email': task.teacher.email,
                # 'homework_file': task.homework_file,
                'start_time': ustime2cntime(task.start_time),
                'end_time': ustime2cntime(task.end_time),
                'start_time_raw':  int(task.start_time.timestamp()*1000),
                'end_time_raw':int(task.end_time.timestamp()*1000),
                'score': task.score,
                'status': task.status,
                'submitted_time': submitted_time,
                'stu_count': models.Course2UserEnrollment.objects.filter(course=course, role='student').count(),
                'score_published': task.score_published,
            }
            return BaseView.successData(homework_detail)
        except Exception as e:
            return BaseView.error(str(e))
    
    
    def getMyTaskList(request):
        try:
            # 获取参数
            params = getParam(request)
            user_id = params.get('user_id')
            is_teacher = params.get('is_teacher')
            course_id = params.get('course_id')
            task_type = params.get('task_type')
            
            if task_type == "homework":
                task_type = "作业"
            elif task_type == "experiment":
                task_type = "实验"
            elif task_type == "exam":
                task_type = "考试"
            else:
                return BaseView.warn('作业类型错误')
            
            course = models.Course.objects.get(course_id=course_id)
            father_homeworks = None
            if course.share_files:
                father_course = models.Course.objects.get(course_id=course.imported_from_course_id)
                father_homeworks = models.Task.objects.filter(task_type=task_type, course=father_course)
            homeworks = models.Task.objects.filter(task_type=task_type, course=course)
            result = []

            if is_teacher == True or is_teacher == 'true':
                # homeworks = models.Task.objects.filter(task_type="作业", course=course)
                pass
            else :
                student = models.Student.objects.get(user_id=user_id)
                stu_submit_records = models.TaskSubmission.objects.filter(student=student, task__in=homeworks)
                # 如果查询到学生已经提交，那么将状态改为已完成。
                # 我的course_id下的所有作业，需要根据学生是否已经提交来判断状态
            exam_count = 0
            for homework in homeworks:
                exam_ongoing = False
                # 判断现在的时间是不是在考试前后1小时
                if homework.task_type == "考试" or homework.task_type == "exam":
                    start_time = timezone.localtime(homework.start_time - timedelta(hours=1), timezone=timezone.get_current_timezone())
                    end_time = timezone.localtime(homework.end_time + timedelta(hours=1), timezone=timezone.get_current_timezone())
                    now_time = timezone.now()
                    if now_time >= start_time and now_time <= end_time:
                        exam_ongoing = True
                        exam_count += 1
                    
                
                start_time = ustime2cntime(homework.start_time)
                end_time = ustime2cntime(homework.end_time)
                time_offset = getTimeOffset(start_time, end_time)
                status = ""
                if time_offset == -1:
                    status = "pending"
                elif time_offset == 0:
                    status = "ongoing"
                else:
                    status = "finished"
                    
                name = homework.name
                description = homework.description
                score = homework.score
                if course.share_files:
                    father_homework = father_homeworks.get(name=homework.name)
                    name = father_homework.name
                    description = father_homework.description
                    score = father_homework.score
                result.append({
                    'task_id': homework.task_id,
                    'task_type': homework.task_type,
                    'name': name,
                    'description': description,
                    'start_time': start_time,
                    'end_time': end_time,
                    'score': score,
                    'status': status,
                    'exam_ongoing': exam_ongoing,
                })
            if is_teacher :
                return BaseView.successData({"task_list":result, "exam_ongoing":False})
            if exam_count == 0:
                return BaseView.successData({"task_list":result, "exam_ongoing":False})
            else:
                result = [item for item in result if item['exam_ongoing'] == True]
                return BaseView.successData({"task_list":result, "exam_ongoing":True})
        except Exception as e:
            return BaseView.error(str(e))
   
    
    def createTask(request):
        try:
            # 获取参数
            params = getParam(request)
            
            task_type = params.get('task_type')
            user_id = params.get('user_id')
            course_id = params.get('course_id')    # 课程
            homework_file = params.get('homework_file')
            name = params.get('name')    # 作业名称
            description = params.get('description')    # 作业描述
            start_time = params.get('start_time')
            end_time = params.get('end_time')
            score = params.get('score')
            
            course = models.Course.objects.get(course_id=course_id)
            if course.share_files:
                father_course_name = models.Course.objects.get(course_id=course.imported_from_course_id).name
                return BaseView.warn(f'共享课程无法创建作业，请在【{father_course_name}】中创建作业')
            
            # 将str的时间换算为timezone格式，以便和timezone.now()比较
            # 传入的时间为2024-04-06T12:05:14.000Z
            offset = getTimeOffset(start_time, end_time)
            if offset == -1:
                status = "pending"
            elif offset == 0:
                status = "ongoing"
            else:
                status = "finished"
            
            if task_type == "homework":
                task_type = "作业"
            elif task_type == "experiment":
                task_type = "实验"
            elif task_type == "exam":
                task_type = "考试"
            else:
                return BaseView.warn('作业类型错误')
            # 创建作业
            teacher = models.Teacher.objects.get(user_id=user_id)
            if task_type == "homework" or task_type == "作业":
                course.homework_count += 1
            elif task_type == "experiment" or task_type == "实验":
                course.experiment_count += 1
            elif task_type == "exam" or task_type == "考试":
                course.exam_count += 1
            course.save()
            task = models.Task.objects.create(
                name=name, 
                description=description, 
                task_type=task_type, 
                course=course, 
                teacher=teacher, 
                start_time=start_time, 
                end_time=end_time, 
                score=score, 
                status=status
                )
            models.Course2Task.objects.create(course=course, task=task)
            for co in models.Course.objects.all():
                if str(co.imported_from_course_id) == str(course_id) and co.share_files:
                    new_task = models.Task.objects.create(name=task.name,
                                                          description=task.description,
                                                          task_type=task.task_type, 
                                                          start_time = task.start_time,
                                                          end_time = task.end_time,
                                                          teacher=teacher,
                                                          imported_from_task_id=task.task_id,
                                                          )
                    models.Course2Task.objects.create(course=co, task=new_task)

            return BaseView.successData(task.task_id)
        except Exception as e:
            return BaseView.error(str(e))
    
   
    def updateTask(request):
        try:
            # 获取参数
            params = getParam(request)
            course_id = str(params.get('course_id'))
            task_id = str(params.get('task_id'))
            task_name = params.get('task_name')
            description = params.get('description')    # 作业描述
            start_time = params.get('start_time')
            end_time = params.get('end_time')
            score = params.get('score')
            offset = getTimeOffset(start_time, end_time)
            if offset == -1:
                status = "pending"
            elif offset == 0:
                status = "ongoing"
            else:
                status = "finished"
            models.Task.objects.filter(task_id=task_id).update(
                name=task_name,
                description=description, 
                start_time=start_time, 
                end_time=end_time, 
                score=score,
                status=status,
                )

            return BaseView.success()
        except Exception as e:
            return BaseView.error(str(e))

